EF 7 définit la valeur par défaut initiale pour la colonne DateTime

c# entity-framework-core

Question

Je dois pouvoir définir la valeur initiale d'une colonne DateTime.

Quand je spécifie "getutcdate () ou DateTime.UtcNow

entity.Property(e => e.ShipDate).DefaultValue("getutcdate()")
entity.Property(e => e.ShipDate).DefaultValue(DateTime.UtcNow)

puis exécutez dnx . ef migration add InitialMigration EF génère un instantané de migration avec:

b.Property<DateTime?>("ShipDate")
  .Required()
  .Annotation("Relational:ColumnDefaultValue", "getutcdate()")
  .Annotation("Relational:ColumnDefaultValueType", "System.String");

quand j'utilise DateTime.UtcNow ...

b.Property<DateTime?>("ShipDate")
  .Annotation("Relational:ColumnDefaultValue", "635754129448768827")
  .Annotation("Relational:ColumnDefaultValueType", "System.DateTime");

et une migration initiale:

ShipDate = table.Column(
  type: "datetime2", 
  nullable: false, 
  defaultValue: "getutcdate()"),

quand j'utilise DateTime.UtcNow ...

ShipDate = table.Column(
  type: "datetime2", 
  nullable: true, 
  defaultValue: new DateTime(2015, 8, 17, 12, 55, 44, 876, DateTimeKind.Unspecified)),

Il semblerait que cela doive fonctionner, mais lorsque j'insère des données dans la table, la valeur par défaut de la colonne est "l'instant" dans lequel l'horodatage a été créé.

Est-ce que je manque quelque chose?

AUSSI, puisque dans le même ordre d'idées, comment spécifier l'IDENTITY SEED dans EF7?

Merci

UPDATE Après avoir généré le script SQL, avec les deux options, je reçois:

Si vous utilisez "getutcdate ()":

[ShipDate] datetime2 DEFAULT 'getutcdate()',

qui ne fonctionne pas à cause des citations

ou si vous utilisez DateTime.utcNow:

[ShipDate] datetime2 DEFAULT '2015-08-17 12:55:44.8760000'

ce qui explique la valeur statique que je recevais.

Je suppose que je peux me débrouiller avec ça. Est-ce un bug ou existe-t-il une manière correcte de le faire? Merci

Réponse acceptée

Vous voulez définir la valeur par défaut SQL, pas une valeur constante:

entity.Property(e => e.ShipDate).HasDefaultValueSql("getutcdate()");

Réponse populaire

Une solution plus flexible utilisant les attributs pour EF Core:

dans votre DbContext:

protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);
    // Add your customizations after calling base.OnModelCreating(builder);
    CustomDataTypeAttributeConvention.Apply(builder);
    DecimalPrecisionAttributeConvention.Apply(builder);
    SqlDefaultValueAttributeConvention.Apply(builder);
}

et créez ces classes:

public static class SqlDefaultValueAttributeConvention
{
    public static void Apply(ModelBuilder builder)
    {
        ConventionBehaviors
            .SetSqlValueForPropertiesWithAttribute<SqlDefaultValueAttribute>(builder, x => x.DefaultValue);
    }
}

public static class DecimalPrecisionAttributeConvention
{
    public static void Apply(ModelBuilder builder)
    {
        ConventionBehaviors
            .SetTypeForPropertiesWithAttribute<DecimalPrecisionAttribute>(builder,
                x => $"decimal({x.Precision}, {x.Scale})");
    }
}

public class CustomDataTypeAttributeConvention
{
    public static void Apply(ModelBuilder builder)
    {
        ConventionBehaviors
            .SetTypeForPropertiesWithAttribute<DataTypeAttribute>(builder,
                x => x.CustomDataType);
    }
}

public static class ConventionBehaviors
{
    public static void SetTypeForPropertiesWithAttribute<TAttribute>(ModelBuilder builder, Func<TAttribute, string> lambda) where TAttribute : class
    {
        SetPropertyValue<TAttribute>(builder).ForEach((x) => {
            x.Item1.Relational().ColumnType = lambda(x.Item2);
        });
    }

    public static void SetSqlValueForPropertiesWithAttribute<TAttribute>(ModelBuilder builder, Func<TAttribute, string> lambda) where TAttribute : class
    {
        SetPropertyValue<TAttribute>(builder).ForEach((x) =>
        {
            x.Item1.Relational().DefaultValueSql = lambda(x.Item2);
        });
    }

    private static List<Tuple<IMutableProperty, TAttribute>> SetPropertyValue<TAttribute>(ModelBuilder builder) where TAttribute : class
    {
        var propsToModify = new List<Tuple<IMutableProperty, TAttribute>>();
        foreach (var entity in builder.Model.GetEntityTypes())
        {
            var properties = entity.GetProperties();
            foreach (var property in properties)
            {
                var attribute = property.PropertyInfo
                    .GetCustomAttributes(typeof(TAttribute), false)
                    .FirstOrDefault() as TAttribute;
                if (attribute != null)
                {
                    propsToModify.Add(new Tuple<IMutableProperty, TAttribute>(property, attribute));
                }
            }
        }
        return propsToModify;
    }
}

et attributs personnalisés:

/// <summary>
/// Set a default value defined on the sql server
/// </summary>
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
public class SqlDefaultValueAttribute : Attribute
{
    /// <summary>
    /// Default value to apply
    /// </summary>
    public string DefaultValue { get; set; }

    /// <summary>
    /// Set a default value defined on the sql server
    /// </summary>
    /// <param name="value">Default value to apply</param>
    public SqlDefaultValueAttribute(string value)
    {
        DefaultValue = value;
    }
}

/// <summary>
/// Set the decimal precision of a decimal sql data type
/// </summary>
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
public class DecimalPrecisionAttribute : Attribute
{
    /// <summary>
    /// Specify the precision - the number of digits both left and right of the decimal
    /// </summary>
    public int Precision { get; set; }

    /// <summary>
    /// Specify the scale - the number of digits to the right of the decimal
    /// </summary>
    public int Scale { get; set; }

    /// <summary>
    /// Set the decimal precision of a decimal sql data type
    /// </summary>
    /// <param name="precision">Specify the precision - the number of digits both left and right of the decimal</param>
    /// <param name="scale">Specify the scale - the number of digits to the right of the decimal</param>
    public DecimalPrecisionAttribute(int precision, int scale)
    {
        Precision = precision;
        Scale = scale;
    }

    public DecimalPrecisionAttribute(int[] values)
    {
        Precision = values[0];
        Scale = values[1];
    }
}

Ensuite, vous pourrez décorer vos propriétés de table avec l’un de ces attributs (ou créer vos propres attributs personnalisés):

[DecimalPrecision(18, 9)] [SqlDefaultValue("getutcdate()")] [DataType("decimal(18,9)")]




Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Est-ce KB légal? Oui, apprenez pourquoi