2015-07-12 80 views
1

確定我在這裏丟失了什麼,或者這只是能夠用數據註釋完成?代碼兩個實體之間的第一個外鍵

我其中有一個外鍵,它添加的文件(一到一個關係)的用戶文檔實體模型:

[Table("Documents", Schema = "Configuration")] 
public class Document : IPrimaryKey { 
    [Key] 
    public long Id { get; set; } 

    [Required] 
    public string OrginalName { get; set; } 

    [Required] 
    public DocumentTypes DocumentType { get; set; } 

    [Required] 
    public MIMETypes MIMEType { get; set; } 

    [Required] 
    public byte[] Data { get; set; } 

    [DefaultValue(false)] 
    public bool IsPublic { get; set; } 

    [Required] 
    public DateTimeOffset DateTimeAdded { get; set; } 

    [Required] 
    public long AddedByUser { get; set; } 

    [ForeignKey("AddedByUser")] 
    public virtual Details Details { get; set; } 
} 

然後我有一個用戶(詳細信息)的實體,可以有圖像文件(存儲在文檔實體模型(無|一個一對一的關係):

[Table("Details", Schema = "User")] 
public class Details : IPrimaryKey { 
    [Key] 
    public long Id { get; set; } 

    [Required] 
    public string UserId { get; set; } 

    [ForeignKey("UserId")] 
    public AppUser User { get; set; } 

    [Required] 
    public string FirstName { get; set; } 

    [Required] 
    public string LastName { get; set; } 

    [CollectionRequired(MinimumCollectionCount = 1)] 
    public ICollection<Address> Addresses { get; set; } 

    [CollectionRequired(MinimumCollectionCount = 1)] 
    public ICollection<Email> Emails { get; set; } 

    [CollectionRequired(MinimumCollectionCount = 1)] 
    public ICollection<PhoneNumber> PhoneNumbers { get; set; } 

    public ICollection<NotificationHistory> NotificationHistory { get; set; } 
    public long TimeZoneId { get; set; } 

    public long? ImageId { get; set; } 

    [ForeignKey("ImageId")] 
    public virtual Document Document { get; set; } 

    [ForeignKey("TimeZoneId")] 
    public virtual TimeZone TimeZone { get; set; } 
} 

當我嘗試創建一個遷移我得到這個錯誤:

Unable to determine the principal end of an association between the types 'StACS.PeoplesVoice.DataAccessLayer.EntityModels.User.Details' and 'StACS.PeoplesVoice.DataAccessLayer.EntityModels.Configuration.Document'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.

更新:

雖然仍在研究這個,我做了兩個變化,並能避開錯誤,但這個創造了一個意外的結果在我的數據庫。

在文檔實體我說:

public virtual ICollection<Details> Details { get; set; } 

在詳細信息(用戶)實體我說:

puflic virtual ICollection<Document> Documents { get; set; } 

在我的數據庫表我現在有我想要的領域外鍵但我分別有一個輔助外鍵。

我試着刪除單個虛擬引用,只留下了ICollection虛擬引用,現在我根本沒有外鍵。

修訂(基於阿卡什卡瓦建議)

我已經做了以下變更 [表( 「文檔」,模式= 「配置」)] 公共類文件:IPrimaryKey { [必須] 公共字符串OrginalName {get;組; }

[Required] 
    public DocumentTypes DocumentType { get; set; } 

    [Required] 
    public MIMETypes MIMEType { get; set; } 

    [Required] 
    public byte[] DocumentData { get; set; } 

    [DefaultValue(false)] 
    public bool IsPublic { get; set; } 

    [Required] 
    public DateTimeOffset DateTimeAdded { get; set; } 

    [Required] 
    public long AddedByUser { get; set; } 

    [Key] 
    public long Id { get; set; } 

    [ForeignKey("AddedByUser")] 

    [InverseProperty("Image")] 

    public virtual Details User { get; set; } 
} 

[Table("Details", Schema = "User")] 
public class Details : IPrimaryKey { 
    [Required] 
    public string UserId { get; set; } 

    [ForeignKey("UserId")] 
    public AppUser User { get; set; } 

    [Required] 
    public string FirstName { get; set; } 

    [Required] 
    public string LastName { get; set; } 

    [CollectionRequired(MinimumCollectionCount = 1)] 
    public ICollection<Address> Addresses { get; set; } 

    [CollectionRequired(MinimumCollectionCount = 1)] 
    public ICollection<Email> Emails { get; set; } 

    [CollectionRequired(MinimumCollectionCount = 1)] 
    public ICollection<PhoneNumber> PhoneNumbers { get; set; } 

    public ICollection<NotificationHistory> NotificationHistory { get; set; } 
    public long TimeZoneId { get; set; } 
    public long? ImageId { get; set; } 

    [ForeignKey("ImageId")] 
    [InverseProperty("User")] 
    public Document Image { get; set; } 

    [ForeignKey("TimeZoneId")] 
    public virtual TimeZone TimeZone { get; set; } 


    [Key] 
    public long Id { get; set; } 
} 

我已經註釋掉流利的API代碼

Unable to determine the principal end of an association between the types 'StACS.PeoplesVoice.DataAccessLayer.EntityModels.User.Details' and 'StACS.PeoplesVoice.DataAccessLayer.EntityModels.Configuration.Document'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.

回答

3

可以達到相同的使用數據標註爲好,你缺少InverseProperty屬性,它解決了不確定性在這種情況下。從概念上講,每個導航屬性都具有反向導航屬性,EF會根據類型自動檢測並假設反向屬性,但如果兩個實體通過多個FK屬性相互關聯,則必須在相應導航屬性上顯式指定InverseProperty屬性。

我建議將InverseProperty放在每個導航屬性上,這有助於縮短EF的啓動時間,因爲EF不必確定並驗證模型。

實施例,

public class AccountEmail { 

    public long AccountID {get;set;} 

    // Inverse property inside Account class 
    // which corresponds to other end of this 
    // relation 
    [InverseProperty("AccountEmails")] 
    [ForeignKey("AccountID")] 
    public Account Account {get;set;} 

} 

public class Account{ 

    // Inverse property inside AccountEmail class 
    // which corresponds to other end of this 
    // relation 
    [InverseProperty("Account")] 
    public ICollection<AccountEmail> AccountEmails {get;set;} 
} 

我已經寫,其基於當前模式中的所有這些導航屬性文本模板。從https://github.com/neurospeech/atoms-mvc.net/tree/master/db-context-tt下載所有三個文件,您可能必須自定義此文件,因爲它基於我們的框架添加了更多內容,但它確實直接從數據庫中生成純代碼模型。

+0

我試過這個,並得到錯誤。如果你能提供一個可行的例子,我會接受你的答案。 –

+0

我已更新我的問題,請檢查它。 –

+0

您的T4模板是否必需?如果是這樣,那麼這將使您的答案無效,因爲數據註釋不適用於此開箱即用。 –

1

OK,我終於想通了這一點。可悲的是,這不是非常直接的,因爲我認爲數據註釋應該可以工作,但事實並非如此。

你必須用流利的API:

 modelBuilder.Entity<Details>() 
        .HasOptional(x => x.Document) 
        .WithMany() 
        .HasForeignKey(x => x.ImageId); 

     modelBuilder.Entity<Document>() 
        .HasRequired(x => x.User) 
        .WithMany() 
        .HasForeignKey(x => x.AddedByUser); 
+0

感謝您分享您的洞察力和解決方案! –

相關問題