2013-02-11 119 views
7

我在我的一個實體上反向導航時遇到問題。與實體框架Fluent API一對一的關係

我有以下兩個對象:

public class Candidate 
{ 
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public long CandidateId { get; set; } 
    .... 

    // Reverse navigation 
    public virtual CandidateData Data { get; set; } 
    ... 

    // Foreign keys 
    .... 
} 

public class CandidateData 
{ 
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public long CandidateDataId { get; set; } 

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

    // Foreign keys 
    [ForeignKey("CandidateId")] 
    public virtual Candidate Candidate { get; set; } 
} 

現在CandidateData對象上我的外鍵導航工作正常。我無法獲得候選對象的反向導航工作(如果甚至可能的話)。

這是我OnModelCreating功能:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
{ 
    modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 

    modelBuilder.Entity<Candidate>() 
     .HasOptional(obj => obj.Data) 
     .WithOptionalPrincipal(); 

    base.OnModelCreating(modelBuilder); 
} 

這是接近,除了在數據庫中的工作,我得到鏈接到CandidateId兩列。我從POCO對象中獲得一個我得到的另一列Candidate_CandidateId,我假設它是由modelBuilder創建的。

我現在安靜地迷失了。有人可以澄清一下發生了什麼嗎?

+0

爲什麼要定義像 這樣的附加字段[必須] public long CandidateId {get;組; } 刪除它,你的問題將會消失 – 2013-02-11 10:20:45

+0

我認爲你的關係應該是modelBuilder.Entity ().HasOptional(obj => obj.Data).WithRequired(e => e.Candidate);順便說一句:儘量不要混合流利的api和屬性。 – tschmit007 2013-02-11 10:38:29

回答

13

一對一問題.... 問題是EF和CODE首先,當1:1時,對於依賴關係來說,有一個指向主體的主鍵。雖然你可以定義一個數據庫,但事實上也可以使用數據庫,你甚至可以在主數據庫上有可選的FK。 EF首先在代碼中對此進行限制。很公平,我認爲......

試試這個:是增加了關於您可能忽略如果你不同意:-)

using System.ComponentModel.DataAnnotations; 
using System.ComponentModel.DataAnnotations.Schema; 
using System.Data.Entity; 
namespace EF_DEMO 
{ 
class FK121 
{ 
    public static void ENTRYfk121(string[] args) 
    { 
     var ctx = new Context121(); 
     ctx.Database.Create(); 
     System.Console.ReadKey(); 
    } 
} 
public class Candidate 
{ 
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]// best in Fluent API, In my opinion.. 
    public long CandidateId { get; set; } 
// public long CandidateDataId { get; set; }// DONT TRY THIS... Although DB will support EF cant deal with 1:1 and both as FKs 
    public virtual CandidateData Data { get; set; } // Reverse navigation 

} 
public class CandidateData 
{ 
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)] // best in Fluent API as it is EF/DB related 
    public long CandidateDataId { get; set; } // is also a Foreign with EF and 1:1 when this is dependent 
    // [Required] 
    // public long CandidateId { get; set; } // dont need this... PK is the FK to Principal in 1:1 
    public virtual Candidate Candidate { get; set; } // yes we need this 
} 
public class Context121 : DbContext 
{ 
    static Context121() 
    { 
     Database.SetInitializer(new DropCreateDatabaseIfModelChanges<Context121>()); 
    } 
    public Context121() 
     : base("Name=Demo") { } 
    public DbSet<Candidate> Candidates { get; set; } 
    public DbSet<CandidateData> CandidateDatas { get; set; } 

    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Candidate>(); 

     modelBuilder.Entity<CandidateData>() 
        .HasRequired(q => q.Candidate) 
        .WithOptional(p=>p.Data) // this would be blank if reverse validation wasnt used, but here it is used 
        .Map(t => t.MapKey("CandidateId")); // Only use MAP when the Foreign Key Attributes NOT annotated as attributes 
    } 
} 

}

+0

謝謝,這或多或少地爲我解決了這個問題。 儘管我仍然希望CandidateId字段可供我隨時編輯,而無需加載候選對象。 (或者我解釋錯了嗎?) 再次感謝威廉。 – William 2013-02-12 11:41:44

+0

如果您仍然需要外鍵,您可以將CandidateId保留爲CandidateData上的一個屬性,而不是調用.Map(t => t.MapKey(「CandidateId」)),使用.HasForeignKey(t => t.CandidateId) 這不行嗎? – 2013-03-11 15:09:05

+0

@NathanaelSchulte不幸的是,這不起作用。爲什麼你不能這樣做,我不知道。 .HasForeignKey()方法僅在使用多個時纔可用。 phil soady的方法存在的問題是外鍵CandidateId不能作爲模型的顯式屬性公開,即CandidateId不能在CandidateData類中定義。 – Aernor 2016-04-01 07:47:21

-2

的方式幾意見我認爲外鍵應創建爲: .Map(t => t.MapKey(「CandidateDataId」)),因爲外鍵將被放置在候選表中...

你認爲呢?