EntityFramework不能更新具有默认值的列

25

我通过EntityFramework 4 (EF)将对象插入到SQL Server数据库中。在接收表格中,有一列(CreatedDate),它的默认值设置为getdate()。因此,我不向EF提供它,假设它的值将由SQL Server默认为getdate()

然而,这并没有发生;相反,EF在SaveChanges()中返回一个验证错误。

您知道这种情况发生的原因吗?请告诉我。

非常感谢。


我想这个链接可能会对你有帮助:http://www.ladislavmrnka.com/2011/03/the-bug-in-storegeneratedpattern-fixed-in-vs-2010-sp1/ - V4Vendetta
这里最高评分的答案可能会有所帮助:https://dev59.com/R2Yq5IYBdhLWcg3wjBUM(也可能不会)。 - Chris
7个回答

18
如果您从不想编辑该值(如创建日期),您可以使用以下方法:
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public virtual DateTime CreatedDate { get; set; }

这将告诉Entity Framework该值由数据库控制,但仍会获取该值。

请注意,您不能更改该值,因此如果您只想要初始值,则这不是解决方案。

如果您只想要一个默认值,但仍然可以编辑它,或者您正在使用Entity Framework 5及以下版本,则必须在代码中设置默认值。

有关此问题的更多讨论,请参见:

如何在Entity Framework中使用来自数据库的默认列值?


不是这样的。你可以做到。请看我对这个问题的回答。 - kkahl
虽然不完全正确,但请参考@CptRobby的答案。 - HostMyBus
@kkahl 在回答时是正确的,已经更新了答案。 - mattmanser

2

只需在实体对象定义的列字段上应用[DatabaseGenerated(DatabaseGeneratedOption.Identity)]属性。

例如:

public class SomeTable
{
    ...

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public DateTime CreatedDate { get; set; }

    ...
}

这告诉实体框架,您的列的初始值由数据库提供。插入行后,该值将自动从数据库更新。


对我不起作用 - 我的表中有三个默认值(NEWID()SYSTEM_USERGETDATE()),我用[DatabaseGenerated(DatabaseGeneratedOption.Identity)]标记了这些字段,但是我收到了错误消息 Validation failed for one or more entities. See 'EntityValidationErrors' property for more details. - alex
当然,您肯定想进入调试器并查看附加到异常的额外信息(在EntityValidationErrors属性中)。可能是EntityFramework无法解析/理解其中一个列值。我的经验表明,您可能希望尝试逐个添加这些内容以找到罪魁祸首。我还猜测它最有可能与日期列有关,虽然应该支持,但由于混合了许多日期格式和结构,因此可能很难正确处理。 - kkahl
虽然你的想法是正确的,但正确答案是使用数据注释的 @CptRobby 的答案: [DatabaseGenerated(DatabaseGeneratedOption.Computed)] - HostMyBus
是的,将DateTime列作为标识列是非常不常见的。 - Gert Arnold

2
这个问题的正确答案是告诉实体框架该列是计算列。
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public virtual DateTime CreatedDate { get; set; }
DatabaseGeneratedOption.Computed 表示该值由数据库设置,不能被 Entity Framework 更改。 DatabaseGeneratedOption.Identity 表示该列是一个 IDENTITY 列,应该只用于自动递增的数字主键。

请注意,DatabaseGeneratedOption 枚举的文档 没有提到 IDENTITY 列(部分原因是因为它是 SqlServer 特定的实现细节)。相反,它将 Identity 选项定义为“插入行时数据库生成一个值。”我实际上正在寻找一种方法,允许在创建记录时使用 DEFAULT 约束设置 ModDate,但在更新记录时允许从 Entity Framework 进行修改。因此,由于描述,我认为我可能已经找到了解决方案,但尝试修改带有 DatabaseGeneratedOption.Identity 标志的记录的 ModDate 时引发了异常。所以没有那么幸运。


0
我不知道这是否仍然相关。但我今天遇到了这个问题,并通过以下步骤进行了修复:
1. 打开 Model.edmx 文件 2. 选择数据库中具有默认值的表格和字段 3. 右键点击字段,选择“属性” 4. 将“StoreGeneratedPattern”的值更改为“Computed”

enter image description here


0

您可以在实体数据模型的 GUI 中设置 StoreGeneratedPattern 为 Computed(如 Malcolm 所建议的)。

在 Visual Studio 中打开您的 .edmx 文件 打开字段的属性(单击字段 -> 按下 F4右键单击->属性) 在下面的 属性窗口 中将 StoreGeneratedPattern 设置为 Computed,如下所示:

Entity Framework - default values doesn't set in SQL server table


0

尝试使用这个。

public virtual DateTime CreatedDate { get; set; } = new Datetime();

要注意这种方法和使用数据库列GetDate()默认值之间的固有差异。这将在实例化对象时设置CreatedDate,这可能是一个非常不同的日期和时间,与数据库记录创建的时间不同。它也可能处于不同的时区。 - undefined

-1
为了开始工作,我声明了一个新的变量,并将该变量设置为当前时间。然后,在插入数据时,我将变量引用到了相应的列中。
var db = new YourTableEntities();
var dateNow = DateTime.Now; 

db.YourTableEntities.Add(new YourTableEntities()
{
    ColumnAInTable = someAVariable,
    ColumnBInTable = someBVariable,
    ColumnThatShouldDefaultToGetDate = dateNow
});

希望这能帮到你!


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