Valore predefinito per i campi obbligatori nelle migrazioni di Entity Framework?


91

Ho aggiunto l' [Required]annotazione dei dati a uno dei miei modelli in un'applicazione ASP.NET MVC . Dopo aver creato una migrazione, l'esecuzione del Update-Databasecomando genera il seguente errore:

Impossibile inserire il valore NULL nella colonna "Director", tabella "MOVIES_cf7bad808fa94f89afa2e5dae1161e78.dbo.Movies"; la colonna non consente valori nulli. UPDATE non riesce. La dichiarazione è stata terminata.

Ciò è dovuto ad alcuni record che hanno NULL nelle Directorcolonne. Come posso modificare automaticamente questi valori in un regista predefinito (ad esempio "John Doe")?

Ecco il mio modello:

  public class Movie
    {
        public int ID { get; set; }
        [Required]
        public string Title { get; set; }

        [DataType(DataType.Date)]
        public DateTime ReleaseDate { get; set; }

        [Required]
        public string Genre { get; set; }

        [Range(1,100)]
        [DataType(DataType.Currency)]
        public decimal Price { get; set; }

        [StringLength(5)]
        public string Rating { get; set; }

        [Required]     /// <--- NEW
        public string Director { get; set; }
    }

ed ecco la mia ultima migrazione:

public partial class AddDataAnnotationsMig : DbMigration
{
    public override void Up()
    {
        AlterColumn("dbo.Movies", "Title", c => c.String(nullable: false));
        AlterColumn("dbo.Movies", "Genre", c => c.String(nullable: false));
        AlterColumn("dbo.Movies", "Rating", c => c.String(maxLength: 5));
        AlterColumn("dbo.Movies", "Director", c => c.String(nullable: false));
    }

    public override void Down()
    {
        AlterColumn("dbo.Movies", "Director", c => c.String());
        AlterColumn("dbo.Movies", "Rating", c => c.String());
        AlterColumn("dbo.Movies", "Genre", c => c.String());
        AlterColumn("dbo.Movies", "Title", c => c.String());
    }
}

Risposte:


74

Se ricordo bene, qualcosa del genere dovrebbe funzionare:

AlterColumn("dbo.Movies", "Director", c => c.String(nullable: false, defaultValueSql: "'John Doe'"));

Nota: il valore del parametro defaultValueSql viene trattato come un'istruzione SQL verbatim, quindi se il valore richiesto è effettivamente una stringa, come l'esempio di John Doe, sono necessarie virgolette singole intorno al valore.


9
Lo pensavo anch'io, ma non sembra funzionare per i dischi esistenti. Quindi ricevo ancora un errore.
Andriy Drozdyuk

@drozzy Forse è un bug, come qui: EF 4.3.1 Eccezione di migrazione - AlterColumn defaultValueSql crea lo stesso nome di vincolo predefinito per tabelle diverse È possibile aggiornare le righe con il IS NULLcontrollo dalla query.
webdeveloper

Interessante, ma non sono sicuro di aver capito di cosa stanno parlando. Tuttavia, se questo è un bug, allora sì, avrebbe senso.
Andriy Drozdyuk

6
Penso che dovrebbe essere: "'John Doe'"- devi usare virgolette SQL.
Sean

1
@webdeveloper, non credo sia un bug, perché AlterColumnaggiornare i valori correnti? È un comando DDL (non DML).
Anton il

110

Oltre alla risposta di @webdeveloper e @Pushpendra, è necessario aggiungere manualmente aggiornamenti alla migrazione per aggiornare le righe esistenti. Per esempio:

public override void Up()
{
    Sql("UPDATE [dbo].[Movies] SET Title = 'No Title' WHERE Title IS NULL");
    AlterColumn("dbo.Movies", "Title", c => c.String(nullable: false,defaultValue:"MyTitle"));
}

Questo perché AlterColumnproduce DDL per impostare il valore predefinito della colonna su un valore specifico nella specifica della tabella. Il DDL non influisce sulle righe esistenti nel database.

In realtà stai apportando due modifiche allo stesso tempo (impostando il valore predefinito e rendendo la colonna NOT NULL) e ognuna di esse è valida individualmente, ma poiché stai effettuando le due contemporaneamente, puoi aspettarti che il sistema lo faccia ' intelligentemente 'realizza il tuo intento e imposta tutto NULL valori sul valore predefinito, ma questo non è ciò che ci si aspetta sempre.

Supponi di impostare solo il valore predefinito per la colonna e di non renderlo NOT NULL. Ovviamente non ti aspetti che tutti i record NULL vengano aggiornati con l'impostazione predefinita che fornisci.

Quindi, secondo me, questo non è un bug e non voglio che EF aggiorni i miei dati nei modi in cui non gli dico esplicitamente di farlo. Lo sviluppatore è responsabile di istruire il sistema su cosa fare con i dati.


17
Per le persone che trovano questa risposta tramite Google: l'ho appena provato in EF6 e la dichiarazione di aggiornamento non sembra essere necessaria (più). Immagino che lo considerassero un bug, dopotutto.
EPLKleijntjens

3
Posso anche garantire per quello. Se è necessario un valore predefinito anche per un campo nullable, è sufficiente modificarlo prima in non annullabile con un valore predefinito, quindi modificarlo nuovamente in nullable. Molto utile per quando hai aggiunto un campo non annullabile a una classe figlio :)
Wouter Schut

1
Spot sulla spiegazione. AlterColumn () altera solo la definizione della colonna. Non influisce in alcun modo sui record esistenti
Korayem il

10
public partial class AddDataAnnotationsMig : DbMigration
{
    public override void Up()
    {
        AlterColumn("dbo.Movies", "Title", c => c.String(nullable: false,defaultValue:"MyTitle"));
        AlterColumn("dbo.Movies", "Genre", c => c.String(nullable: false,defaultValue:"Genre"));
        AlterColumn("dbo.Movies", "Rating", c => c.String(maxLength: 5));
        AlterColumn("dbo.Movies", "Director", c => c.String(nullable: false,defaultValue:"Director"));

    }

    public override void Down()
    {       
        AlterColumn("dbo.Movies", "Director", c => c.String());
        AlterColumn("dbo.Movies", "Rating", c => c.String());
        AlterColumn("dbo.Movies", "Genre", c => c.String());
        AlterColumn("dbo.Movies", "Title", c => c.String());       
    }
}

2
Uhm ... grazie, ma in cosa differisce dalla risposta di @ webdeveloper?
Andriy Drozdyuk

1
non ti dice dove devi aggiungere il parametro del valore predefinito
Pushpendra

1
@Pushpendra, è divertente come gli sviluppatori tendano a dimenticare che una volta non sapevano molto. Mi piacciono le risposte dettagliate che soddisfano tutti i livelli. Lavoro eccellente!
Utile Bee

5

non sono sicuro che questa opzione fosse sempre disponibile, ma ho riscontrato un problema simile, ho scoperto che ero in grado di impostare il valore predefinito senza eseguire aggiornamenti manuali utilizzando quanto segue

defaultValueSql: "'NY'"

Ho ricevuto un errore quando il valore fornito è stato "NY"poi mi sono reso conto che si aspettavano un valore SQL come "GETDATE()"così ho provato "'NY'"e ha funzionato

l'intera linea ha questo aspetto

AddColumn("TABLE_NAME", "State", c => c.String(maxLength: 2, nullable: false, defaultValueSql: "'NY'"));

Grazie a questa risposta , mi ha messo sulla strada giusta


2

Ho scoperto che il solo utilizzo di Auto-Property Initializer sulla proprietà dell'entità è sufficiente per completare il lavoro.

Per esempio:

public class Thing {
    public bool IsBigThing { get; set; } = false;
}

2
È una buona risposta (mi ha aiutato), ma questo non aggiunge un valore predefinito nel database, imposta il valore nel codice.
chris31389

giusto, non ha aggiunto il valore predefinito nel database dopo le modifiche alla migrazione
Chetan Chaudhari

2

Molte delle altre risposte si concentrano su come intervenire manualmente quando si verificano questi problemi.

Dopo aver generato la migrazione, eseguire una delle seguenti modifiche alla migrazione:

  1. Modificare la definizione della colonna per includere un'istruzione defaultValue o defaultSql:
    AlterColumn("dbo.Movies", "Director", c => c.String(nullable: false, default: ""));

  2. Iniettare un'istruzione SQL per precompilare le colonne esistenti, prima dell'AlterColumn:
    Sql("UPDATE dbo.Movies SET Director = '' WHERE Director IS NULL");

Tieni presente che le modifiche manuali applicate a uno script di migrazione verranno sovrascritte se imposti nuovamente la migrazione. Per la prima soluzione, è abbastanza facile estendere EF per definire automaticamente un valore predefinito su un campo come parte della generazione della migrazione.

NOTA: EF non lo fa automaticamente perché l'implementazione del valore predefinito sarebbe diversa per ogni provider RDBMS, ma anche perché i valori predefiniti hanno meno significato in un runtime EF puro perché ogni inserimento di riga fornirà il valore corrente per ogni proprietà, anche se è nullo, il vincolo del valore predefinito non viene mai valutato.
Questa istruzione AlterColumn è l'unica volta in cui entra in gioco il vincolo predefinito, immagino che questa sia diventata una priorità inferiore per il team che ha progettato l'implementazione della migrazione di SQL Server.

La soluzione seguente combina la notazione degli attributi, le convenzioni di configurazione del modello e le annotazioni di colonna per passare i metadati a un generatore di codice di migrazione personalizzato. I passaggi 1 e 2 possono essere sostituiti con una notazione fluente per ogni campo interessato se non si utilizza la notazione per attributi.
Ci sono molte tecniche in gioco qui, sentiti libero di usarne alcune o tutte, spero che ci sia valore per tutti qui


  1. Dichiarare il valore predefinito
    Creare o riutilizzare un attributo esistente per definire il valore predefinito da utilizzare, per questo esempio creeremo un nuovo attributo chiamato DefaultValue che eredita da ComponentModel.DefaultValueAttribute, poiché l'utilizzo è intuitivo ed è possibile che esista le basi di codice implementano già questo attributo. Con questa implementazione è sufficiente utilizzare questo attributo specifico per accedere a DefaultValueSql, utile per le date e altri scenari personalizzati.

    Implementazione

    [DefaultValue("Insert DefaultValue Here")]
    [Required]     /// <--- NEW
    public string Director { get; set; }
    
    // Example of default value sql
    [DefaultValue(DefaultValueSql: "GetDate()")]
    [Required]
    public string LastModified { get; set; }

    Definizione di attrributo

    namespace EFExtensions
    {
        /// <summary>
        /// Specifies the default value for a property but allows a custom SQL statement to be provided as well. <see cref="MiniTuber.Database.Conventions.DefaultValueConvention"/>
        /// </summary>
        public class DefaultValueAttribute : System.ComponentModel.DefaultValueAttribute
        {
            /// <summary>
            /// Specifies the default value for a property but allows a custom SQL statement to be provided as well. <see cref="MiniTuber.Database.Conventions.DefaultValueConvention"/>
            /// </summary>
            public DefaultValueAttribute() : base("")
            {
            }
    
            /// <i
            /// <summary>
            /// Optional SQL to use to specify the default value.
            /// </summary>
            public string DefaultSql { get; set; }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a Unicode character.
            /// </summary>
            /// <param name="value">
            /// A Unicode character that is the default value.
            /// </param>
            public DefaultValueAttribute(char value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using an 8-bit unsigned integer.
            /// </summary>
            /// <param name="value">
            /// An 8-bit unsigned integer that is the default value.
            /// </param>
            public DefaultValueAttribute(byte value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a 16-bit signed integer.
            /// </summary>
            /// <param name="value">
            /// A 16-bit signed integer that is the default value.
            /// </param>
            public DefaultValueAttribute(short value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a 32-bit signed integer.
            /// </summary>
            /// <param name="value">
            /// A 32-bit signed integer that is the default value.
            /// </param>
            public DefaultValueAttribute(int value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a 64-bit signed integer.
            /// </summary>
            /// <param name="value">
            /// A 64-bit signed integer that is the default value.
            /// </param>
            public DefaultValueAttribute(long value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a single-precision floating point number.
            /// </summary>
            /// <param name="value">
            /// A single-precision floating point number that is the default value.
            /// </param>
            public DefaultValueAttribute(float value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a double-precision floating point number.
            /// </summary>
            /// <param name="value">
            /// A double-precision floating point number that is the default value.
            /// </param>
            public DefaultValueAttribute(double value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a System.Boolean value.
            /// </summary>
            /// <param name="value">
            /// A System.Boolean that is the default value.
            /// </param>
            public DefaultValueAttribute(bool value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class using a System.String.
            /// </summary>
            /// <param name="value">
            /// A System.String that is the default value.
            /// </param>
            public DefaultValueAttribute(string value) : base(value) { }
    
            /// <summary>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class.
            /// </summary>
            /// <param name="value">
            /// An System.Object that represents the default value.
            /// </param>
            public DefaultValueAttribute(object value) : base(value) { }
    
            /// /// <inheritdoc/>
            /// Initializes a new instance of the System.ComponentModel.DefaultValueAttribute
            /// class, converting the specified value to the specified type, and using an invariant
            /// culture as the translation context.
            /// </summary>
            /// <param name="type">
            /// A System.Type that represents the type to convert the value to.
            /// </param>
            /// <param name="value">
            /// A System.String that can be converted to the type using the System.ComponentModel.TypeConverter
            /// for the type and the U.S. English culture.
            /// </param>
            public DefaultValueAttribute(Type type, string value) : base(value) { }
        }
    }
  2. Creare una convenzione per inserire il valore predefinito nelle annotazioni di colonna Le annotazioni di
    colonna vengono utilizzate per passare metadati personalizzati sulle colonne al generatore di script di migrazione.
    L'utilizzo di una convenzione per fare ciò dimostra il potere dietro la notazione degli attributi per semplificare il modo in cui i metadati fluenti possono essere definiti e manipolati per molte proprietà piuttosto che specificarli individualmente per ogni campo.

    namespace EFExtensions
    {
    
        /// <summary>
        /// Implement SQL Default Values from System.ComponentModel.DefaultValueAttribute
        /// </summary>
        public class DefaultValueConvention : Convention
        {
            /// <summary>
            /// Annotation Key to use for Default Values specified directly as an object
            /// </summary>
            public const string DirectValueAnnotationKey = "DefaultValue";
            /// <summary>
            /// Annotation Key to use for Default Values specified as SQL Strings
            /// </summary>
            public const string SqlValueAnnotationKey = "DefaultSql";
    
            /// <summary>
            /// Implement SQL Default Values from System.ComponentModel.DefaultValueAttribute
            /// </summary>
            public DefaultValueConvention()
            {
                // Implement SO Default Value Attributes first
                this.Properties()
                        .Where(x => x.HasAttribute<EFExtensions.DefaultValueAttribute>())
                        .Configure(c => c.HasColumnAnnotation(
                            c.GetAttribute<EFExtensions.DefaultValueAttribute>().GetDefaultValueAttributeKey(),
                            c.GetAttribute<EFExtensions.DefaultValueAttribute>().GetDefaultValueAttributeValue()
                            ));
    
                // Implement Component Model Default Value Attributes, but only if it is not the SO implementation
                this.Properties()
                        .Where(x => x.HasAttribute<System.ComponentModel.DefaultValueAttribute>())
                        .Where(x => !x.HasAttribute<MiniTuber.DataAnnotations.DefaultValueAttribute>())
                        .Configure(c => c.HasColumnAnnotation(
                            DefaultValueConvention.DirectValueAnnotationKey, 
                            c.GetAttribute<System.ComponentModel.DefaultValueAttribute>().Value
                            ));
            }
        }
    
        /// <summary>
        /// Extension Methods to simplify the logic for building column annotations for Default Value processing
        /// </summary>
        public static partial class PropertyInfoAttributeExtensions
        {
            /// <summary>
            /// Wrapper to simplify the lookup for a specific attribute on a property info.
            /// </summary>
            /// <typeparam name="T">Type of attribute to lookup</typeparam>
            /// <param name="self">PropertyInfo to inspect</param>
            /// <returns>True if an attribute of the requested type exists</returns>
            public static bool HasAttribute<T>(this PropertyInfo self) where T : Attribute
            {
                return self.GetCustomAttributes(false).OfType<T>().Any();
            }
    
            /// <summary>
            /// Wrapper to return the first attribute of the specified type
            /// </summary>
            /// <typeparam name="T">Type of attribute to return</typeparam>
            /// <param name="self">PropertyInfo to inspect</param>
            /// <returns>First attribuite that matches the requested type</returns>
            public static T GetAttribute<T>(this System.Data.Entity.ModelConfiguration.Configuration.ConventionPrimitivePropertyConfiguration self) where T : Attribute
            {
                return self.ClrPropertyInfo.GetCustomAttributes(false).OfType<T>().First();
            }
    
            /// <summary>
            /// Helper to select the correct DefaultValue annotation key based on the attribute values
            /// </summary>
            /// <param name="self"></param>
            /// <returns></returns>
            public static string GetDefaultValueAttributeKey(this EFExtensions.DefaultValueAttribute self)
            {
                return String.IsNullOrWhiteSpace(self.DefaultSql) ? DefaultValueConvention.DirectValueAnnotationKey : DefaultValueConvention.SqlValueAnnotationKey;
            }
    
            /// <summary>
            /// Helper to select the correct attribute property to send as a DefaultValue annotation value
            /// </summary>
            /// <param name="self"></param>
            /// <returns></returns>
            public static object GetDefaultValueAttributeValue(this EFExtensions.DefaultValueAttribute self)
            {
                return String.IsNullOrWhiteSpace(self.DefaultSql) ? self.Value : self.DefaultSql;
            }
        }
    
    }
  3. Aggiungi la convenzione al DbContext
    Ci sono molti modi per ottenere questo, mi piace dichiarare le convenzioni come il primo passaggio personalizzato nella mia logica ModelCreation, questo sarà nella tua classe DbContext.

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        // Use our new DefaultValueConvention
        modelBuilder.Conventions.Add<EFExtensions.DefaultValueConvention>();
    
        // My personal favourites ;)
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
    
    }
  4. Sostituire il MigrationCodeGenerator
    Ora che queste annotazioni sono state applicate alle definizioni di colonna all'interno del modello, è necessario modificare il generatore di script di migrazione per utilizzare quelle annotazioni. Per questo erediteremo dal System.Data.Entity.Migrations.Design.CSharpMigrationCodeGeneratorcome abbiamo solo bisogno di iniettare una quantità minima di cambiamento.
    Una volta elaborata la nostra annotazione personalizzata, dobbiamo rimuoverla dalla definizione della colonna per evitare che venga serializzata nell'output finale.

    Consulta il codice della classe base per esplorare altri utilizzi: http://entityframework.codeplex.com/sourcecontrol/latest#src/EntityFramework/Migrations/Design/CSharpMigrationCodeGenerator.cs

    namespace EFExtensions
    {
        /// <summary>
        /// Implement DefaultValue constraint definition in Migration Scripts.
        /// </summary>
        /// <remarks>
        /// Original guide that provided inspiration for this https://romiller.com/2012/11/30/code-first-migrations-customizing-scaffolded-code/
        /// </remarks>
        public class CustomCodeGenerator : System.Data.Entity.Migrations.Design.CSharpMigrationCodeGenerator
        {
            /// <summary>
            /// Inject Default values from the DefaultValue attribute, if the DefaultValueConvention has been enabled.
            /// </summary>
            /// <seealso cref="DefaultValueConvention"/>
            /// <param name="column"></param>
            /// <param name="writer"></param>
            /// <param name="emitName"></param>
            protected override void Generate(ColumnModel column, IndentedTextWriter writer, bool emitName = false)
            {
                var annotations = column.Annotations?.ToList();
                if (annotations != null && annotations.Any())
                {
                    for (int index = 0; index < annotations.Count; index ++)
                    {
                        var annotation = annotations[index];
                        bool handled = true;
    
                        try
                        {
                            switch (annotation.Key)
                            {
                                case DefaultValueConvention.SqlValueAnnotationKey:
                                    if (annotation.Value?.NewValue != null)
                                    {
                                        column.DefaultValueSql = $"{annotation.Value.NewValue}";
                                    }
                                    break;
                                case DefaultValueConvention.DirectValueAnnotationKey:
                                    if (annotation.Value?.NewValue != null)
                                    {
                                        column.DefaultValue = Convert.ChangeType(annotation.Value.NewValue, column.ClrType);
                                    }
                                    break;
                                default:
                                    handled = false;
                                    break;
                            }
                        }
                        catch(Exception ex)
                        {
                            // re-throw with specific debug information
                            throw new ApplicationException($"Failed to Implement Column Annotation for column: {column.Name} with key: {annotation.Key} and new value: {annotation.Value.NewValue}", ex);
                        }
    
                        if(handled)
                        {
                            // remove the annotation, it has been applied
                            column.Annotations.Remove(annotation.Key);
                        }
                    }
                }
                base.Generate(column, writer, emitName);
            }
    
            /// <summary>
            /// Generates class summary comments and default attributes
            /// </summary>
            /// <param name="writer"> Text writer to add the generated code to. </param>
            /// <param name="designer"> A value indicating if this class is being generated for a code-behind file. </param>
            protected override void WriteClassAttributes(IndentedTextWriter writer, bool designer)
            {
                writer.WriteLine("/// <summary>");
                writer.WriteLine("/// Definition of the Migration: {0}", this.ClassName);
                writer.WriteLine("/// </summary>");
                writer.WriteLine("/// <remarks>");
                writer.WriteLine("/// Generated Time: {0}", DateTime.Now);
                writer.WriteLine("/// Generated By: {0}", Environment.UserName);
                writer.WriteLine("/// </remarks>");
                base.WriteClassAttributes(writer, designer);
            }
    
    
        }
    }
  5. Registra il CustomCodeGenerator
    Ultimo passaggio, nel file di configurazione di DbMigration dobbiamo specificare il generatore di codice da utilizzare, cerca Configuration.cs nella cartella Migration per impostazione predefinita ...

    internal sealed class Configuration : DbMigrationsConfiguration<YourApplication.Database.Context>
    {
        public Configuration()
        {
            // I recommend that auto-migrations be disabled so that we control
            // the migrations explicitly 
            AutomaticMigrationsEnabled = false;
            CodeGenerator = new EFExtensions.CustomCodeGenerator();
        }
    
        protected override void Seed(YourApplication.Database.Context context)
        {
            //   Your custom seed logic here
        }
    }

2

A partire da EF Core 2.1, puoi usare MigrationBuilder.UpdateDataper modificare i valori prima di alterare la colonna (più pulito rispetto all'uso di SQL non elaborato):

protected override void Up(MigrationBuilder migrationBuilder)
{
    // Change existing NULL values to NOT NULL values
    migrationBuilder.UpdateData(
        table: tableName,
        column: columnName,
        value: valueInsteadOfNull,
        keyColumn: columnName,
        keyValue: null);

    // Change column type to NOT NULL
    migrationBuilder.AlterColumn<ColumnType>(
        table: tableName,
        name: columnName,
        nullable: false,
        oldClrType: typeof(ColumnType),
        oldNullable: true);
}

0

Per qualche motivo, che non sono stato in grado di spiegarmi, la risposta approvata non funziona più per me.

Ha funzionato su un'altra app, su quella su cui sto lavorando no.

Quindi, una soluzione alternativa, ma piuttosto inefficiente , sarebbe sovrascrivere il metodo SaveChanges () come mostrato di seguito. Questo metodo dovrebbe essere nella classe Context.

    public override int SaveChanges()
    {
        foreach (var entry in ChangeTracker.Entries().Where(entry => entry.Entity.GetType().GetProperty("ColumnName") != null))
        {
            if (entry.State == EntityState.Added)
            {
                entry.Property("ColumnName").CurrentValue = "DefaultValue";
            }
        }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.