entity framework – 在sql server表中未设置默认值
SQL Server 2005数据库表有一个“createdon”列,其默认值设置为getdate()。 我试图使用entity framework添加记录。 ‘createdon’列未获得更新。
我是否错过了Entity框架中的任何属性,请提出建议。
这是Entity Framework中存在问题的少数几个问题之一。 假设您有一个类似于以下的类:
public class MyEntity { // Id is a PK on the table with Auto-Increment public int Id { get; set; } // CreatedOn is a datetime, with a default value public DateTime CreatedOn { get; set; } }
现在,您要插入一个新元素:
using(var context = new YourContext()) { context.MyEntities.Add(new MyEntity()) }
由于EDMX中的定义,entity framework知道如何处理自动增量主键。 它不会尝试为Id
属性插入值。 但是,就entity framework而言, CreatedOn
具有一个值:默认的DateTime
。 因为entity framework不能说“好,它有一个值,但我应该忽略它”,它会主动插入带有CreatedOn
属性值的记录,绕过表CreatedOn
定义的默认值。
没有简单的方法可以做到这一点。 插入该项时,可以主动将CreatedOn
属性设置为DateTime.Now
。 或者您可以创建一个接口和一个扩展方法对:
public interface ICreatedOn { public DateTime CreatedOn { get; set; } } public partial class MyEntity : ICreatedOn { } public static TEntity AsNew(this TEntity entity) where TEntity : ICreatedOn { if(entity != null) entity.CreatedOn = DateTime.Now; return entity; } using(var context = new YourContext()) { context.MyEntities.Add(new MyEntity().AsNew()) }
编辑:为了扩展这一点,这是一个无法解决的问题的原因是因为autoincrement
字段和具有default
值约束的字段背后的含义。 根据定义,自动增量字段应始终由服务器使用种子和所有爵士乐来处理。 除非已使用SET IDENTITY INSERT ON
否则无法为插入上的自动增量字段指定值。 但是,默认值只是提示“如果我没有指定任何值,请使用此”。 因为.NET中的值类型不能为null,所以总会有一个值,并且Entity Framework无法推断该字段的默认值(当时)意味着您希望它在SQL Server上默认值。
您也可以在实体数据模型的GUI中将StoreGeneratedPattern
设置为Computed
(如Malcolm建议的那样)。
- 在Visual Studio中打开.edmx文件
- 打开字段的属性(单击字段 – >点击F4或右键单击 – >属性)
- 将
StoreGeneratedPattern
设置为在属性窗口中Computed
,如下所示:
我通过告诉EF该列是“已计算”来解决这个问题,因此应该单独插入。
如果查看生成的实体的配置
namespace Data.Context { // Table internal partial class MyTableConfiguration : EntityTypeConfiguration { public MyTableConfiguration(string schema = "dbo") { ToTable(schema + ".MyTable"); HasKey(x => x.Id); Property(x => x.ColumnName).HasColumnName("ColumnName").IsOptional().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed); ....
在使用设计器和已经显示的一些更好的东西之后,您还可以通过在字段上设置DatabaseGenerated
属性将列标记为计算:
[DatabaseGenerated(DatabaseGeneratedOption.Computed)] public DateTime CreatedOn { get; set; }