entity framework代码首先将Guid用作另一个标识列的标识

如何在Code First中创build多个标识列?

由于集群性能,常见的build议是使用自动增量整数列而不是使用newid()创build的GUID。

为了将列声明为自动增量,必须使用Annotation [DatabaseGenerated(DatabaseGeneratedOption.Identity)]指定它。

但是,你只能在一个表中有一个身份。

因此,从一个基本模型开始,如:

 public abstract class ModelBase { // the primary key public virtual Guid Id { get; set; } // a unique autoincrementing key public virtual int ClusterId { get; set; } } 

我们如何设置它以便:

  1. Guid是由数据库自动生成的,而不是代码
  2. ClusterId是自动增量的
  3. entity framework代码首先不会抛出各种类似的错误:
    • 不支持将主键列的属性“StoreGeneratedPattern”设置为“计算”的表的修改。 改用“身份”模式。

仅供参考 ,如果您确实想在代码中自动生成它,则可以跳过Id字段的注释,并执行如下操作:

 public abstract class AbstractContext : DbContext { /// <summary> /// Custom processing when saving entities in changetracker /// </summary> /// <returns></returns> public override int SaveChanges() { // recommended to explicitly set New Guid for appropriate entities -- http://msdn.microsoft.com/en-us/library/dd283139.aspx foreach (var entry in ChangeTracker.Entries<ModelBase>().Where(e => e.State == EntityState.Added) ) { // only generate if property isn't identity... Type t = entry.Entity.GetType(); var info = t.GetProperty("Id").GetCustomAttributes( typeof(DatabaseGeneratedAttribute), true).Cast<DatabaseGeneratedAttribute>().Single(); if (info.DatabaseGeneratedOption != DatabaseGeneratedOption.Identity) { entry.Entity.Id = Guid.NewGuid(); // now we make it } } return base.SaveChanges(); } } 

这最终为我工作,entity framework5。

  1. closures自动迁移
  2. 迁移到创build初始表,没有装饰
  3. ClusterId声明为标识(注释)

     [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public override int ClusterId { get; set; } 
  4. 迁移

  5. 另一个更新后,将pk属性Id声明为Identity

     [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public override Guid Id { get; set; } 
    • 奖金 :EF似乎认为Id是主键,所以你不需要[Key, Required]
  6. add-migration TrickEfIntoAutogeneratingMultipleColumns一样创build迁移代码

  7. Up()方法中,在AlterColumn语句中,通过声明defaultSqlValue来通知数据库自动生成GUID
    • AlterColumn(theTable, "Id", c => c.Guid(nullable: false, identity: true, defaultValueSql: "newid()"));
  8. 迁移

这似乎“欺骗”了EF,因为它假设两列都是身份,并作出相应的反应。 在迁移过程中,它会尝试使另一个列成为一个标识,但是看起来并不在意,当它悄无声息地失败时 – 最终会有一个标识为标识,另一个标识为缺省值。

在正常的代码操作期间,当EF经历SaveChanges / ChangeTracking步骤时,因为它将Id属性看作是Identity,它完全是“分配临时密钥” ,所以它不会尝试使用默认的0000000 …值,而是让数据库使用您指定的默认值函数来生成它。

(我会认为注释这个领域作为Computed会完成相同的事情,但…我在问题中提到的错误…嘘…)

而且,因为ClusterId字段也是代码中的标识,并且实际上是数据库中的标识,所以它也自动增量。