Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there an easy way to make EntityFramework use SQL default values?

For example, most of my entities have DateCreated and DateModified fields. The defaults to these are set to GetUtcDate() in SQL Server.

If I try and create an entity and don't set these values, I get an exception saying it can't run the SQL insert because the date value is out of range. Makes sense because C# default dates are 1/1/0001 while SQL Server's minimum date is 1/1/1753.

So is there a way I can tell EF to either use the SQL Server default values, or to NOT try and insert columns which have not been set?

like image 635
Rachel Avatar asked May 11 '11 13:05

Rachel


People also ask

How do I set default value in EDMX?

edmx viewer select an entity -> go the column -> properties -> Default Value. Add the default value for the column in it and that's it.

Which constraint can be used to provide a default value?

The DEFAULT constraint is used to set a default value for a column. The default value will be added to all new records, if no other value is specified.


2 Answers

You must set StoreGeneratedPattern for those properties to Identity for DateCreated and Computed for DataModified. It is available in designer. Once you do that you cannot modify those values in your application - only database can set those properties. I wrote about this some article because this feature had bug before VS2010 SP1 but there are reports that it still doesn't work sometimes.

like image 79
Ladislav Mrnka Avatar answered Nov 16 '22 02:11

Ladislav Mrnka


One solution is to override your generated entitycontext class by using partial. This will intercept inserts/updates on all the entity classes in your EF context:

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.HasProperty("DateCreated"))
                insert.Entity.GetType().GetProperty("DateCreated").SetValue(insert.Entity, DateTime.UtcNow, null);
            if (insert.Entity.HasProperty("LastModified"))
                insert.Entity.GetType().GetProperty("LastModified").SetValue(insert.Entity, DateTime.UtcNow, null);
        }

        foreach (var update in this.ObjectStateManager.GetObjectStateEntries(System.Data.EntityState.Modified))
        {
            if (update.Entity.HasProperty("LastModified"))
                update.Entity.GetType().GetProperty("LastModified").SetValue(update.Entity, DateTime.UtcNow, null);
        }

        return base.SaveChanges(options);
    }
}

Or do something similar, looking for inserts/updates on your datestamp fields and removing them from the ObjectStateEntries collection?

like image 32
James McCormack Avatar answered Nov 16 '22 01:11

James McCormack