4

Assuming I have the following table in my DB:

CREATE TABLE [dbo].[Test]
(
    [Id]      INT            IDENTITY (1, 1) NOT NULL,
    [Active]  BIT            DEFAULT ((1)) NOT NULL,
)

When creating an EF model from this DB, the mapping for the Active bit column, which is mapped to a Boolean column, has no default value (see property "Default Value): Property View - Model Diagram

Why does Entity Framework behave that way? Why doesn't the default value that is defined in the database automatically be applied in the model when the model gets created? The DB states that the default value should be 1, which I assumed would be a default value of true in the model. Do I really have to set the default value for all my columns in the model again?

I checked this behaviour for int and bit columns.


I did some more investigation, and tried to set the "Default Value" property by hand to True and true, and both works.

Manually changed default value

The auto-generated constructor for the Test-entity changes from

public Test()
{
}

to

public Test()
{
    this.Active = true;
}

So default values would be possible in EF, but they are not set when generating the model based on database-first, at least not on my machine.

So, the question still remains: Do I really have to set the default value for all my columns in the model again, even if they are already set in the DB?

Markus Weninger
  • 11,931
  • 7
  • 64
  • 137
  • 3
    I have to admit that I mixed up two concepts of "default value" when thinking about this. DB default = If a null value is provided for a given column, use the default value. EF default = If a new instance of a certain entity is created, for each property set the default value (e.g. in the constructor). And these two behaviors are conceputally not the same. – Markus Weninger Oct 29 '16 at 16:17
  • 1
    But i would expect EF to take DB-Defaults to your created model as a "default" as well. So the developer just has to change, what has to be changed, but not to have a look at thousands of columns with default values... Otherwise why is a property like "not null" read from db? it could be null in EF, if there is a trigger to handle nulls ot something...??? – swe Oct 31 '16 at 09:45
  • @swe -> Yes, that's also the the way I expected it to work: Creating an instance of some entity (like `Test t = new Test()`) would be filled with the default values. So `ctx.Tests.Add(t); ctx.SaveChanges();` would result in a new entry in the database, containing an _Test_-entry with `Active = 1`, because `Active` "has not been set set manually" (like you said "only change what has to be changed") and therefore should use the default value. But it seems that's not how EF works... – Markus Weninger Oct 31 '16 at 11:53
  • 1
    Not sure why EF does this, but because of problems like this I usually maintain at least two other `.sql` files along with the one the model generates: `ExtraSQL.sql` and `InitialData.sql`. "extra sql" are things like these default values; additional SQL rules that need to be applied that aren't easily done through EF. "initial data" is any data that needs to be in the system for it to function. Then I can execute the three scripts and immediately have a working system. – Dave Cousineau Apr 17 '17 at 02:17
  • @MarkusWeninger, DB default means when you don't use the column in the insert statement that's when DB put's default value, otherwise it will insert the null value if column allows null or will give error. – sallushan Sep 30 '17 at 13:07

3 Answers3

5

Try this:

StoreGeneratedPattern = Calculated

Edit:

Sorry for the one-code-line answer but I really was in a hurry last day.

To make EF set a property’s db default value, the fastest way is to open your .edmx designer, click on the interested field and set

StoreGeneratedPattern = Calculated

In its properties (you can see this property in your second screenshot, where you set “default value” to true).

  • Please add more explanation. – J...S Sep 30 '17 at 13:02
  • The "StoreGeneratedPattern" value is "Computed", not "Calculated" I assume that is what you actually meant. The problem with that might be that if you would not like to ALWAYS have default value from database, this in my case worked rather poorly. Since if I assign a value within the code while creating an entity, the value will get overwritten by databases default value. – CrookedBadge May 28 '20 at 13:42
0

This solution solve for all entities that has same property such as CreatedDateTime

public partial class MyEntities : ObjectContext
    {
        public override int SaveChanges(SaveOptions options)
        {
            this.DetectChanges();

            foreach (var insert in this.ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Added))
            {
                if (insert.Entity.GetType().GetProperty("CreatedDateTime") != null && insert.Entity.GetType().GetProperty("CreatedDateTime").GetType().Name == "DateTime" && (DateTime)(insert.Entity.GetType().GetProperty("CreatedDateTime").GetValue(insert.Entity)) == DateTime.Parse("0001-01-01 00:00:00.0000000"))
                    insert.Entity.GetType().GetProperty("CreatedDateTime").SetValue(insert.Entity, DateTime.UtcNow, null);                
            }
            return base.SaveChanges(options);
        }
    }

referance: https://stackoverflow.com/a/5965743/7731479

Leo
  • 398
  • 6
  • 11
0

My workaround is to create a partial class and define a constructor, which sets the variables that have default values automatically. This doesn't solve your initial problem, but at least you don't have to set the default values after every update.

public partial class Test
{
    public Test()
    {
        this.Active = true;
    }
} 
bryanbcook
  • 16,210
  • 2
  • 40
  • 69
Cratz3r
  • 1
  • 1