2014-10-30 49 views
0

我正在使用实体框架Code-First重建一个用于从Access数据库运行的应用程序。其中一项要求是,新的数据模式应该是可审​​计的,这是它应该显示谁创造了一个纪录,谁更新它,什么时候等自引用外键

我创建了一个基础机构类,如下所示:

public class Entity 
{ 
    public int Id { get; set; } 

    public int CreatedByUserId { get; set; } 
    public int? UpdatedByUserId { get; set; } 

    public virtual User CreatedBy { get; set; } 
    public virtual User UpdatedBy { get; set; } 
} 

然后,我创建了一个从EntityTypeConfiguration继承如下

public class BaseEntityTypeConfiguration<T> : EntityTypeConfiguration<T> where T : Entity 
{ 
    Property(e => e.Id).HasColumnName(typeof(T).Name + "Id"); 

    HasRequired(e => e.CreatedBy).WithMany().HasForeignKey(e => e.CreatedById); 
    HasOptional(e => e.UpdatedBy).WithMany().HasForeignKey(e => e.UpdatedById); 
} 

现在我创建一个从BaseEntityTypeConfiguration继承,从我的实体类继承我的业务类的其他配置的类。

问题是当我试图让我的用户类从实体继承如下:

public class User : Entity 
{ 
    public string Username { get; set; } 
    // etc 
} 

我会增加对记录的“鬼”用户如果证据不存在,以确定谁创造了这个记录,但是这个幽灵用户本质上是自己创造的。

我越来越从实体框架下面的错误,当我尝试添加这鬼用户:

Unable to determine a valid ordering for dependent operations. Dependencies may exist due to foreign key constraints, model requirements or store-generated values. 

有可能在我的域模型的问题,可能会造成这个错误,但我的理论是,这是试图在这种情况下创建自己的用户。

是否有自引用外键约束有问题?

回答

1

您的PK是一个身份列,您正在设置幽灵用户的CreatedByUser属性。这会导致鸡/鸡蛋情况 - 您需要User.Id值作为User.CreatedById值来将记录插入到数据库表中,但在插入记录之前您不知道什么是User.Id

如果您可以确定身份的种子值(EF似乎默认为1),则可以将CreatedByUserId属性设置为该值而不是CreatedByUser

否则,通过执行SQL语句创建您的幽灵用户,允许您手动将IdCreatedByUserId字段设置为相同的值,然后将其身份重新设置为Id + 1。前者的

实施例:

public class UserWithCreatedBy 
{ 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 

    public int CreatedById { get; set; } 

    [ForeignKey("CreatedById")] 
    public UserWithCreatedBy CreatedBy { get; set; } 
} 


static void Main(string[] args) 
{ 
    using(var db = new TestContext()) 
    { 
     var u = new UserWithCreatedBy(); 

     // doesn't work with identity 
     //u.CreatedBy = u; 

     // this will work as long as you know what the identity seed is 
     // (whatever the next identity value will be) 
     u.CreatedById = 1; 

     db.UsersWithCreatedBy.Add(u); 

     db.SaveChanges(); 
    } 
}