当前位置: 首页 > 编程语言 > C#

如何让EF6在INSERT期间处理数据库上的DEFAULTCONSTRAINT分享

时间:2023-04-10 22:38:06 C#

如何让EF6在INSERT期间处理数据库上的DEFAULTCONSTRAINT到数据库或编程。其他人也问过类似的问题,但我觉得没有问到正确的细节,或者解释得太糟糕以至于需要解释,所以我走了。问题:如何让EntityFramework正确处理在执行INSERT时定义了DEFAULTCONSTRAINT的数据库中的列?这意味着,如果我在插入操作期间没有在模型中提供值,我如何让EF从它生成的TSQLINSERT命令中排除该列,以便数据库定义的DEFAULTCONSTRAINT起作用?背景我有一个简单的表,我只是为了测试EntityFramework6(EF6)及其与SQLServer能够更新的列的交互而创建的。这使用IDENTITY、TIMESTAMP、COMPUTED和一些应用了DEFAULTCONSTRAINT的列。在GO上设置ANSI_NULLS在GO上设置QUOTED_IDENTIFIER创建表[dbo].[DBUpdateTest]([RowID][int]IDENTITY(200,1)NOTNULL,[UserValue][int]NOTNULL,[DefValue1][int]NOTNULL,[DefValue2null][int]NULL,[DefSecond][int]NOTNULL,[CalcValue]AS(((([rowid]+[uservalue])+[defvalue1])+[defvalue2null])*[defsecond]),[RowTimestamp][timestamp]NULL,CONSTRAINT[PK_DBUpdateTest]主键集群([RowID]ASC)WITH(PAD_INDEX=OFF,STATISTICS_NORECOMPUTE=OFF,IGNORE_DUP_KEY=OFF,ALLOW_ROW_LOCKS=ON,ALLOW_PAGE_LOCKS=ON))GOALTERTABLE[dbo].[DBUpdateTest]添加约束[DF_DBUpdateTest_DefValue1]DEFAULT((200))FOR[DefValue1]GOALTERTABLE[dbo].[DBUpdateTest]添加约束[DF_DBUpdateTest_DefValue2null]DEFAULT((30))FOR[DefValue2null]GOALTERTABLE[dbo].[DBUpdateTest]ADDCONSTRAINT[DF_DBUpdateTest_DefSecond]DEFAULT(datepart(second,getdate()))FOR[DefSecond]GOEF6完成美地处理IDENTITY,TIMESTAMP和COMPUTED列,这意味着在INSERT或UP在DATE之后(通过context.SaveChanges()),EF将新值读回实体对象以供立即使用,但是,对于具有DEFAULTCONSTRAINT的列,不会发生这种情况。据我所知,这是因为当EF生成TSQL来执行INSERT时,它为可为null或不可为null的类型提供了一个公共默认值,就好像该列没有定义DEFAULTCONSTRAINT一样。所以很明显EF完全忽略了DEFAULTCONSTRAINT的可能性。这是我用于插入DBUpdateTest记录的EF代码(我只更新一列):DBUpdateTestmyVal=newDBUpdateTest();myVal.UserValue=RND.Next(20,90);DB.DBUpdateTests.Add(myVal);DB。保存更改();这是EF在INSERT到DBUpdateTest期间生成的SQL(它忠实地更新所有可能的列):@0,@1,NULL,@2)从[dbo].[DBUpdateTest]选择[RowID],[CalcValue],[RowTimestamp]WHERE@@ROWCOUNT>0AND[RowID]=scope_identity()',N'@0int,@1int,@2int',@0=86,@1=0,@2=54注意里面很明确的规定了INTNOTNULL(0)和INTNULL(空)的默认值,这完全克服了默认约束。这是执行EFINSERT命令时发生的情况,它为可空列提供NULL,为INT列提供零RowIDUserValueDefValue1DefValue2nullDefSecondCalcValue==========================================================================211100200NULL0NULL另一方面,如果我执行这条语句:insertintoDBUpdateTest(UserValue)values(100)我得到这样的记录RowIDUserValueDefValue1DefValue2nullDefSecondCalcValue==========================================================================2111002003073787这工作正常有一个原因:TSQLINSERT命令没有为定义了DEFAULTCONSTRAINT的任何列提供值.所以我想做的是让EF从INSERTTSQL中排除DEFAULTCONSTRAINT列,如果我没有在模型对象中明确设置它们的值的话。我尝试过的事情1.识别默认约束?所以:如何让EF处理默认约束在我的DbContext类的OnModelCreating()方法中,建议我告诉EF具有DEFAULTCONSTRAINT的列是计算字段,而不是。但是,我想知道在INSERT之后它是否会让EF至少读回值(更不用说它也可能阻止我为列赋值,这只是我不想要的):modelBuilder.Entity().Property(e=>e.DefValue1).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);这不起作用,实际上似乎没有任何区别(ED:实际上它确实起作用,请参见第2点)。EF仍然生成相同的TSQL,为列提供默认值并在此过程中破坏数据库。是否有一个我丢失的标志,一个我忘记设置的配置项,一个我可以使用的函数属性,一些我可以创建继承以使EF“正确处理DEFAULTCONSTRAINT列”的类代码?2.让OnModelCreating()执行?SO:OnModelCreatingnotcalledJanesh(下方)向我展示了如果列标记为DatabaseGeneratedOption.Computed,EF将从它生成的TSQLINSERT命令中删除参数。它只是对我不起作用,因为显然我使用了错误的连接字符串(!!!)。这是我的App.config,这是我显示“坏”和“好”连接字符串的部分:区别:有效的使用System.Data.SqlClientProviderName,无效的使用System.Data。实体客户。显然,SqlClient提供程序允许使用OnModelCreating()方法,这使我可以使用DatabaseGeneratedOption.Computed来生效。==========未解决==========列上的默认约束的目的是允许我提供(或不提供)一个值并且仍然以有效结束数据库端的值。我不必知道SQLServer正在执行此操作,或者默认设置是什么或应该是什么。这完全超出了我的控制或知识范围。关键是,我可以选择不提供价值。我可以提供它,也可以不提供,如果需要,我可以为每个INSERT做不同的事情。对于这种情况,使用DatabaseGeneratedOption.Computed实际上不是一个有效的选项,因为它会强制做出选择:“您始终可以提供一个值(因此永远不会利用数据库默认机制),或者您永远不能提供一个值(因此始终是使用数据库默认机制)”。此外,此选项显然仅用于实际计算列,而不用于具有DEFAULTCONSTRAINT的列,因为一旦应用,模型属性实际上变为READ-ONLY对于INSERT和UPDATE-因为这是一个真正的计算列将起作用。显然,这让我无法选择提供或不提供数据库的值。所以,我还是要问:如何让EF正确使用定义了DEFAULTCONSTRAINT的数据库列?这一点是您问题的症结所在:所以我所做的是,如果我没有在对象中为它们显式设置值,我不会让EFNOT在其INSERTTSQL中包含DEFAULTCONSTRAINT列。实体框架不会为你做那件事。字段要么始终计算,要么始终包含在插入和更新中。但是,您可以编写类以按照您描述的方式运行。您必须在构造函数中(明确地)将该字段设置为默认值,或使用支持字段。publicclassDBUpdateTest/*publicpartialclassDBUpdateTest*///数据库版本优先{private_DefValue1=200;私人_DefValue2=30;publicDbUpdateTest(){DefSecond=DateTime.Second;}公共DefSecond{得到;放;Val}publicDef{get{return_DefValue1;}设置{_DefValue1=值;}}publicDefValue2{get{return_DefValue2;}设置{_DefValue2=值;如果你总是插入这些类,那么你可能不需要在数据库中插入设置默认值,但是如果你从其他地方使用sql插入,那么你还必须向数据库添加默认约束我强烈不同意DatabaseGeneratedOption.Computed无助于停止在insertsql命令中发送字段。我尝试验证它是否适用于最小的小示例。注意:将DatabaseGeneratedOption.Computed应用于任何属性后,您希望能够在EF中指定任何值。也就是说,插入或更新记录时不能指定任何值。模型publicclassPerson{publicintId{get;放;}publicintSomeId{得到;放;}公共字符串名称{得到;放;}}上下文publicclassContext:DbContext{publicDbSetPeople{get;放;}protectedoverridevoidOnModelCreating(DbModelBuildermodelBuilder){modelBuilder.Entity().HasKey(d=>d.Id);modelBuilder.Entity().Property(d=>d.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);modelBuilder.Entity().Property(d=>d.SomeId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);}}移民publicpartialclassInitial:DbMigration{publicoverridevoidUp(){CreateTable("dbo.People",c=>new{Id=c.Int(nullable:false,identity:true),SomeId=c.Int(nullable:false,defaultValue:3),//我手动编辑它以分配默认值3.Name=c.String(),}).PrimaryKey(t=>t.Id);}publicoverridevoidDown(){DropTable("dbo.People");}}注意:我手动将默认值3编辑为SomeId。主程序:staticvoidMain(string[]args){using(Contextc=newContext()){Personp=newPerson();p.Name="詹尼什";c.People.Add(p);c.Database.Log=Console.WriteLine;c.SaveChanges();我将以下查询记录到我的控制台:Openedconnectionat04/15/201511:32:19AM+05:30Startedtransactionat04/15/201511:32:19AM+05:30INSERT[dbo].[People]([Name])VALUES(@0)SELECT[Id],[SomeId]FROM[dbo].[People]WHERE@@ROWCOUNT>0AND[Id]=scope_identity()--@0:'Jenish'(Type=String,Size=-1)--Executingat04/15/201511:32:20AM+05:30--在3ms内完成,结果:SqlDataReaderCommittedtransactionat04/15/201511:32:20AM+05:30Closedconnectionat04/15/201511:32:20AM+05:30注意SomeId尚未传递给Insert命令,但在select命令中被选中。我相信有人在2013/2014年回答了这个问题:)。该项目正在使用EF5,请注意!他告诉我:右键单击.edmx,选择“打开方式”,然后选择“XML(文本)编辑器”,找到文件部分中设置为默认约束的列。然后在这些字段的末尾添加StoreGeneratedPattern="Computed"。完成,然后就可以了。然后我转移到EF6,它仍然有效,但之前不行。现在,我在使用EF6版本6.1.3时遇到了一个非常有趣的问题。此刻,我有两个带有默认约束的表,将一个布尔字段设置为1,记录是ACTIVE还是INACTIVE。就这么简单。在一张表中,它可以工作,这意味着:我不必将此StoreGeneratedPattern="Computed"添加到.edmx中的列。但是,在另一个表中,它没有;我必须将这个StoreGeneratedPattern="Computed"添加到与表1相同的列。以上是C#学习教程:如何让EF6在INSERT时处理数据库上DEFAULTCONSTRAINT共享的所有内容。如果对你有用,需要了解更多C#学习教程,希望大家多加关注——本文来自网络收集,不代表立场,如涉及侵权,请点击有权联系管理员删除。如需转载请注明出处: