How to get EF 6 to handle DEFAULT CONSTRAINT on a database during INSERT

我的梦境 提交于 2019-12-04 23:59:53

This bit is the key to your question:

What I am trying to do, therefore, is to get EF NOT to include the DEFAULT CONSTRAINT columns in its INSERT TSQL if I do not explcitly set values for them in the object.

Entity Framework won't do that for you. Fields are either always computed or always included in inserts and updates. But you CAN write the classes to behave in the way that you describe. You have to set the fields (explicitly) to the default values in the constructor, or using backing fields.

public class DBUpdateTest
/* public partial class DBUpdateTest*/ //version for database first
{
   private _DefValue1 = 200;
   private _DefValue2 = 30;

   public DbUpdateTest()
   {
      DefSecond = DateTime.Second;
   }

   public DefSecond { get; set; }

   public DefValue1
   {
      get { return _DefValue1; }
      set { _DefValue1 = value; }
   }

   public DefValue2
   {
      get { return _DefValue2; }
      set { _DefValue2 = value; }
   }
}

If you always insert using these classes, then you probably don't need to set the default in the database, but if you insert using sql from elsewhere, then you will have to add the default constraint to the database too

I strongly disagree that DatabaseGeneratedOption.Computed does not help to stop sending the field in insert sql command. I tried that with minimal small example to verify and it worked.

Note: Once you applied DatabaseGeneratedOption.Computed to any property then you want be able to specify any value from EF. i.e. you can not specify any value while inserting or updating records.

Model

public class Person
{
    public int Id { get; set; }
    public int SomeId { get; set; }
    public string Name { get; set; }
}

Context

public class Context : DbContext
{
    public DbSet<Person> People { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Person>().HasKey(d => d.Id);
        modelBuilder.Entity<Person>()
            .Property(d => d.Id)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
        modelBuilder.Entity<Person>()
            .Property(d => d.SomeId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
    }
}

Migration

public partial class Initial : DbMigration
{
    public override void Up()
    {
        CreateTable(
            "dbo.People",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    SomeId = c.Int(nullable: false, defaultValue:3), //I edited it mannually to assign default value 3.
                    Name = c.String(),
                })
            .PrimaryKey(t => t.Id);

    }

    public override void Down()
    {
        DropTable("dbo.People");
    }
}

Note: I edited default value 3 to SomeId manually.

MainProgram:

    static void Main(string[] args)
    {
        using (Context c = new Context())
        {
            Person p = new Person();
            p.Name = "Jenish";
            c.People.Add(p);
            c.Database.Log = Console.WriteLine;
            c.SaveChanges();
        }
    }

I got following query logged to my console:

Opened connection at 04/15/2015 11:32:19 AM +05:30

Started transaction at 04/15/2015 11:32:19 AM +05:30

INSERT [dbo].[People]([Name])
VALUES (@0)
SELECT [Id], [SomeId]
FROM [dbo].[People]
WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()


-- @0: 'Jenish' (Type = String, Size = -1)

-- Executing at 04/15/2015 11:32:20 AM +05:30

-- Completed in 3 ms with result: SqlDataReader



Committed transaction at 04/15/2015 11:32:20 AM +05:30

Closed connection at 04/15/2015 11:32:20 AM +05:30

Notice SomeId have not been passed to Insert command instead it is being selected in select command.

Mephisto

Someone answered this question back in 2013/2014, I believe :). The project was using EF5, ok, mind that! He told me:

  1. Right-click on your .edmx, choose "Open With", then "XML (Text) Editor", and find your columns that you set as Default Constraint inside the <!-- SSDL content --> section of the file.
  2. Then add StoreGeneratedPattern="Computed" at the end of these fields.

Done, then it worked.

Then I moved to EF6 and it STILL works, but WITHOUT the addition made before.

Now, I face a very interesting problem, using EF6, version 6.1.3. At this very moment, I have 2 tables with a Default Constraint to set a boolean field to 1, whether the record is ACTIVE or INACTIVE. Simple as that.

In one table it works, meaning: I don't have to add this StoreGeneratedPattern="Computed" to the column inside .edmx. But, in the other table, IT DOESN'T; I DO have to add this StoreGeneratedPattern="Computed" to the very same column as the table 1.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!