创建Entity Framework模型时忽略了数据库默认值

4

假设我在我的数据库中有以下表格:

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

当从此数据库创建EF模型时,映射到布尔列的Active 位(bit)列的映射没有默认值(请参见属性“默认值”): 属性视图 - 模型图 为什么Entity Framework会这样表现?为什么在创建模型时,数据库中定义的默认值不会自动应用于模型?数据库指定默认值应为1,我认为这将是模型中true的默认值。我真的需要再次为模型中的所有列设置默认值吗?
我检查了intbit列的这种行为。

我进行了更多的调查,尝试手动将“默认值”属性设置为Truetrue,两者都有效。

Manually changed default value

自动生成的Test实体构造函数从以下内容更改:
public Test()
{
}

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

EF中可以使用默认值,但在基于数据库的模型生成过程中,默认值并未设置,至少在我的机器上没有设置。

因此,问题仍然存在:即使列在数据库中已经设置了默认值,我是否仍然需要在模型中再次设置默认值?


3
我必须承认,在思考这个问题时,我混淆了“默认值”的两个概念。数据库默认值 = 如果给定列提供了空值,则使用默认值。实体框架默认值 = 如果创建某个实体的新实例,为每个属性设置默认值(例如在构造函数中)。而这两个行为在概念上并不相同。 - Markus Weninger
1
但是我希望EF也能将DB-Defaults作为“默认”应用于您创建的模型。因此,开发人员只需更改需要更改的内容,而不必查看具有默认值的数千个列...否则,为什么会从数据库中读取“非空”属性?如果有触发器来处理nulls或其他内容,它在EF中可能为空...??? - swe
@swe -> 是的,这也是我期望它工作的方式:创建某个实体的实例(例如 Test t = new Test())将填充默认值。因此,ctx.Tests.Add(t); ctx.SaveChanges(); 将在数据库中生成一个新条目,其中包含一个带有 Active = 1Test 条目,因为 Active "未被手动设置"(就像你说的 "只更改必须更改的内容"),因此应使用默认值。 但似乎 EF 不是这样工作的... - Markus Weninger
1
不确定为什么EF会这样做,但是由于像这样的问题,我通常至少维护另外两个.sql文件与模型生成的文件一起:ExtraSQL.sqlInitialData.sql。 "额外的SQL"是这些默认值;需要应用的其他SQL规则,这些规则不能通过EF轻松完成。 "初始数据"是系统中需要的任何数据,以使其正常运行。然后,我可以执行这三个脚本,并立即拥有一个工作系统。 - Dave Cousineau
@MarkusWeninger,DB默认值是指当您在插入语句中不使用该列时,DB会放置默认值,否则如果该列允许为空,则会插入空值或者会出现错误。 - sallushan
3个回答

5

试试这个:

StoreGeneratedPattern = Calculated

编辑:

很抱歉前一天只回答了一行代码,我当时非常匆忙。

要让EF设置属性的数据库默认值,最快的方法是打开您的.edmx设计器,单击感兴趣的字段,然后设置

StoreGeneratedPattern = Calculated

在其属性中(您可以在第二个屏幕截图中看到此属性,在那里您将“默认值”设置为true)。


请添加更多的解释。 - J...S
"StoreGeneratedPattern"的值为"Computed",而不是"Calculated",我想这可能是你实际想要的。但问题在于,如果你不想总是从数据库获取默认值,在我的情况下,这种方法效果不佳。因为如果我在创建实体时在代码中分配一个值,该值将被数据库的默认值覆盖。 - CrookedBadge

0
我的解决方法是创建一个部分类并定义一个构造函数,在该构造函数中自动设置具有默认值的变量。这并不能解决您最初的问题,但至少您不必在每次更新后重新设置默认值。
public partial class Test
{
    public Test()
    {
        this.Active = true;
    }
} 

他们不必在每次更新时设置值。 - Gert Arnold

0

这个解决方案适用于所有具有相同属性(例如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);
        }
    }

参考资料:https://dev59.com/8G025IYBdhLWcg3wf2OE#5965743


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接