2014-10-30 78 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(); 
    } 
}