C# 实体框架不包括insert into查询中具有默认值的列

C# 实体框架不包括insert into查询中具有默认值的列,c#,entity-framework,entity-framework-core,C#,Entity Framework,Entity Framework Core,我有一个模型,它有一些用默认值定义的列,比如 table.Column<bool>(nullable: false, defaultValueSql: "1") 我正在使用工作单元和存储库,因此 _unitOfWork.MyModelRepository.Add(newModel); _unitOfWork.SaveChanges(); 在VS的输出窗口中,我看到它如何将INSERT中的所有属性发送到查询中,然后对具有默认值的属性执行选择。结果是数据库中的newModel包含了我

我有一个模型,它有一些用默认值定义的列,比如

table.Column<bool>(nullable: false, defaultValueSql: "1")
我正在使用工作单元和存储库,因此

_unitOfWork.MyModelRepository.Add(newModel);
_unitOfWork.SaveChanges();
在VS的输出窗口中,我看到它如何将
INSERT中的所有属性发送到
查询中,然后对具有默认值的属性执行
选择
。结果是数据库中的newModel包含了我发送的所有值,除了包含默认值的列。 我无法更改这些表的配置,因为它正被另一个需要这些规则的系统使用


我想知道为什么会发生这种情况,而不仅仅是一个解决方案。我可以解决这个问题,但我想知道,如果不使用适当的属性将属性标记为计算属性,为什么会发生这种行为

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]  
ef将生成带有属性值的insert语句。
在更新期间,EF生成update语句集子句,只插入更改的值


无论如何,您已经有了一个解决方法,如果属性仅由DBMS生成,那么您可以使用上面的属性,否则您必须在表示实体的类的构造函数中插入默认值。

我将此称为错误

我抓拍了一个简单的测试,只是一个带有一些默认值的类:

public class Test
{
    public int ID { get; set; }
    public int IntDef { get; set; }
    public bool BoolDef { get; set; }
    public DateTime? DateDef { get; set; }
}
(请注意,DateTime可为空)

映射:

modelBuilder.Entity<Test>().HasKey(a => a.ID);
modelBuilder.Entity<Test>().Property(s => s.DateDef).HasDefaultValueSql("GETDATE()");
modelBuilder.Entity<Test>().Property(s => s.IntDef).HasDefaultValueSql("1");
modelBuilder.Entity<Test>().Property(s => s.BoolDef).HasDefaultValue(true);
// Equivalent:
// modelBuilder.Entity<Test>().Property(s => s.BoolDef).HasDefaultValueSql("1");
当我插入新的
测试
而不设置任何值时,insert语句为:

插入到[测试]
默认值;
选择[ID]、[BoolDef]、[DateDef]、[IntDef]
来自[测试]
其中@@ROWCOUNT=1和[ID]=scope_identity();

您可以看到,在插入之后从数据库中读取三个默认值(以及生成的标识值)。[顺便说一句,这在EF Core中是新的。在EF6中,只有标记为
DatabaseGenerateOption.Computed
的标识值和列值在插入(和更新)后从数据库中读取]

这是创建的
测试
对象:

ID IntDef BoolDef DateDef
1真实的21-11-16 19:52:56
现在,我插入一个新的
测试
并分配所有值,但是,为了好玩,我对不可为空的类型使用默认值:

var项=新测试
{ 
IntDef=默认值(int),//0
BoolDef=default(bool),//false
DateDef=默认值(DateTime),//01-01-01 0:00:00
};
下面是SQL语句:

exec sp_executesql N'SET NOCOUNT ON;
插入到[测试]([日期定义])
数值(@p0);
选择[ID]、[BoolDef]、[IntDef]
来自[测试]
其中@@ROWCOUNT=1和[ID]=scope_identity();
“,N'@p0日期时间2(7)”,@p0='0001-01-01 00:00:00”
当然,EF无法推断默认值是故意指定的。因此,如您所见,仅为可为空的
DateTime
列插入赋值,而不为不可为空的列插入赋值。现在,插入后不会从数据库中读取
DateDef
的值

实体值为:

ID IntDef BoolDef DateDef
1 1真的01-01-01 0:00:00
这与保存实体后所期望的完全不同

这意味着:

如果在EF Core中配置具有默认值的属性,并且此默认值与.Net默认值不同,则不能为.Net类型插入具有默认值的实体(如布尔值的
false

我认为这是一个严重的错误,可能它甚至取消了有关默认值的新EF核心行为的资格

添加
正如Ivan在评论中所说,您可以通过添加
ValueGeneratedNever()
来阻止EF为您设置默认值,例如:

modelBuilder.Entity().Property(s=>s.IntDef)
.HasDefaultValueSql(“1”).ValueGeneratedNever();
现在该值将按原样保存,EF不会在插入和更新后将其读回。总而言之,我认为为不可为null的属性定义默认值是没有用的



使用EF Core 1.1.0预览版进行测试。

一般行为是“列的默认值是插入新行但未为列指定值时将插入的值”。在您的情况下,看起来您正在丢失设置的值。您可以发布代码吗?FWIW,EF6不支持默认值-您必须为所有列显式指定一个值,即使非
NULL
列设置了显式默认值。在这种情况下,您可以删除列的配置以禁用默认值行为,这样默认值将由数据库提供。能否显示您的代码(DbContext、映射、POCO)?请显示您如何映射属性。如果在插入后查询,则必须将其映射为
DatabaseGeneratedOption.Computed
。哪个EF核心版本?
DatabaseGeneratedOption.Computed
表示其值将始终由数据库提供的列,导致EF忽略用户代码对该列的更新。OP只想提供一个默认值,在未指定值时使用,但能够在插入或修改时指定。我同意@bubi,我有其他具有该属性的列,它们工作正常。我的问题是那些具有默认值但未插入valu@CodeCaster问题是不存在未为EF指定的概念(存在被跟踪实体更改的概念)因此,如果您不指定
Computed
EF,它将始终生成insert语句。我将此标记为ANSWERT,因为它确认该行为确实有问题。谢谢只是要补充一点,目前没有办法在运行时动态控制该行为。您所能做的就是使用
ValueGeneratedNever()
静态关闭它。谢谢@Ivan,我还不知道这个。我想我们可以为SO co提出的大量问题做好准备
modelBuilder.Entity<Test>().HasKey(a => a.ID);
modelBuilder.Entity<Test>().Property(s => s.DateDef).HasDefaultValueSql("GETDATE()");
modelBuilder.Entity<Test>().Property(s => s.IntDef).HasDefaultValueSql("1");
modelBuilder.Entity<Test>().Property(s => s.BoolDef).HasDefaultValue(true);
// Equivalent:
// modelBuilder.Entity<Test>().Property(s => s.BoolDef).HasDefaultValueSql("1");