22

見一些背景下一篇:瞭解ForeignKey的屬性首先

Entity framework one to zero or one relationship without navigation property

我以前一直以爲ForeignKey用來顯示哪個屬性的一類認爲,確定的導航ForeignKey的財產,例如

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

    public int? DeferredDataId { get; set; } 
    [ForeignKey("DeferredDataId")] 
    public virtual DeferredData DeferredData { get; set; } 
} 

不過,我發現了鏈接後,這是不對的,作爲DeferredData的主鍵名爲id我真正需要的:

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

    public int? DeferredDataId { get; set; } 
    [ForeignKey("Id")] 
    public virtual DeferredData DeferredData { get; set; } 
} 

ForeignKey用來指向其他類。

我隨後開始改變一些其他的參考文獻:

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

    public int? DeferredDataId { get; set; } 
    [ForeignKey("Id")] 
    public virtual DeferredData DeferredData { get; set; } 

    public int? SignedOffById { get; set; } 
    [ForeignKey("UserId")] 
    public virtual UserProfile SignedOffBy { get; set; } 
} 

但是這並沒有。原來這個ForeignKey需要指向MemberDataSet這個Id類。

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

    public int? DeferredDataId { get; set; } 
    [ForeignKey("Id")] 
    public virtual DeferredData DeferredData { get; set; } 

    public int? SignedOffById { get; set; } 
    [ForeignKey("SignedOffById")] 
    public virtual UserProfile SignedOffBy { get; set; } 
} 

我相信這是因爲該第二關係是一對多而第一是一個0或1,並且有效的關係的主端不同,但是我希望在這個/引用一些清晰度到好的文章,所以我可以理解正在發生的事情以及ForeignKey正在做什麼。

我還在上面的示例中尋找清晰度,以瞭解public int? DeferredDataId { get; set; }DeferredData沒有明確關聯的公式。我很高興這將按照慣例相匹配,但我將如何明確地告訴它,例如如果它有不同的名字?我在這個關於使用ForeignKey屬性的討論中看到的例子,但這不能成爲所有情況下的答案!

所有幫助非常感謝 - 尋求理解問題而不是解決具體問題,因爲我在我的模型中有很多參考,所以需要確定採用哪種方法。

謝謝。

編輯

添加其他類的幫助:

public class DeferredData 
{ 

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

    //other properties 
} 

public class UserProfile 
{ 

    [Key] 
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)] 
    public int UserId { get; set; } 

    //other properties 
} 
+0

檢查標題* enity *框架。 – Agostino

回答

22

需要的一面1 ..0關係MemberDataSet不應該有一個FK到DeferredData。相反,DeferredData的PK也應該是一個FK到MemberDataSet(被稱爲共享主鍵)

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

    public virtual DeferredData DeferredData { get; set; } 
} 

public class DeferredData 
{ 
    // DeferredData.Id is both the PK and a FK to MemberDataSet 
    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.None)] 
    [ForeignKey("MemberDataSet")] 
    public int Id { get; set; } 

    [Required] 
    public virtual MemberDataSet MemberDataSet { get; set; } 
} 

流利的API:

modelBuilder.Entity<MemberDataSet>() 
    .HasOptional(mds => mds.DeferredData) 
    .WithRequired() 
    .WillCascadeOnDelete(); 
+0

因此,所有1對1或1對0..1的關係,你會參考其他類?公衆int如何? DeferredDataId {get;組; }屬性然後適合這個? – Mark007

+1

不,你正在引用當前類的PK字段,它顯然具有相同的名稱「Id」。 'DeferredDataId'不會在這種情況下使用(因爲FK,無論如何) – Moho

+0

好吧,我現在明白了 - 我會更新我的答案 – Moho

0

我認爲你是正確的(前提是我理解你的權利)。 [ForeignKeyAttribute]用於相應的外鍵。不在鏈接對象的主鍵上。

This is my object, and the foreign key is DeferredDataId

無論你對象中的Id是外鍵(它的主鍵),也沒有鏈接對象的ID是外鍵(這是關係的另一側的主鍵)

希望我正確理解你:)因爲我不確定。

+0

我喜歡這個描述「這是我的對象,而外鍵是DeferredDataId」。這就是我一直想到的。然而,這沒有建立數據庫,解決方案是更改爲Id,即每個鏈接的帖子引用其他類。 – Mark007

+0

我檢查過一個我的舊項目。我完全按照這種方式做到了(而且它工作正常)。環境是首先使用sql ce 4和實體框架代碼的數據庫服務。但我認爲這不相關。你有任何錯誤? – csteinmueller

+0

錯誤是「類型'MemberDataSet'上的屬性'DeferredData'上的ForeignKeyAttribute無效。在依賴類型'DeferredData'上未找到外鍵名」DeferredDataId「。我認爲@Moho已經解釋了這個問題,現在開始有所幫助了! – Mark007

0

我認爲你最初的想法是正確的,有一個小小的例外。通過將外鍵放在MemberDataSet上,您意味着您想要一個零或一對多的關係。

在你的例子中,MemberDataSet.DeferredData是可選的,DeferredData可以被許多MemberDataSet實例引用。

用流利的語法,這將表示爲:

modelBuilder.Entity<MemberDataSet>() 
    .HasOptional(dataSet => dataSet.DeferredData) 
    .WithMany() 
    .HasForeignKey(deferredData => deferredData.DeferredDataId); 

爲了使這個一到零或一屬性,你可以把一個唯一的(這裏不爲空)鍵約束在MemberDataSet的DeferredDataId列上。這意味着一個DeferredData實體只能由一個MemberDataSet實體引用。

CREATE UNIQUE INDEX unique_MemberDataSet_DeferredDataId ON MemberDataSet(DeferredDataId) WHERE DeferredDataId IS NOT NULL 

注:This type of filtered key is only available in SQL Server 2008 and up.