2012-10-21 61 views
3

我不能爲我的生活弄清楚這一點。 MSDN上的文章不清楚,看起來過時了。我正在使用EF 5,並試圖爲以下設置單向關係。所以這是我迄今爲止所擁有的。實體框架5 Fluent API - 配置單向關係

public sealed class Capture { 
    /// <summary> 
    /// Get and Set Capture's Unique Identifier. 
    /// </summary> 
    public int Id { get; set; } 

    /// <summary> 
    /// Get and Set Capture's Operating System. 
    /// </summary> 
    public OperatingSystem OperatingSystem { get; set; } 
} 

public sealed class OperatingSystem { 
    /// <summary> 
    /// Operating System's Unique Identifier. 
    /// </summary> 
    public int Id { get; set; } 
} 

internal sealed class EntityCaptureConfiguration : EntityTypeConfiguration<Capture> { 
    /// <summary> 
    /// Create an Entity Capture Configuration. 
    /// </summary> 
    public EntityCaptureConfiguration() { 
     this.ToTable("Capture"); 
     this.HasKey(m => m.Id); 

     this.Property(m => m.Id).HasColumnName("Id"); 

     this.HasRequired(m => m.OperatingSystem).WithRequiredDependent().Map(m => { 
      m.ToTable("OperatingSystem"); 
      m.MapKey("OperatingSystemId"); 
     }); 
    } 
} 

編譯和運行並得到以下運行時異常:「錯誤3034:問題在映射片段起始於線16,46:兩個實體具有可能不同的密鑰被映射到在同一行確保這兩個映射片段將AssociationSet的兩端映射到相應的列

我不禁注意到,沒有任何明確的方法表明我想要使用2個特定的鍵來連接這兩個表。我的意思是我在哪裏指定了子表中的鍵用於父表中的連接?

這是我需要幫助:

  1. 我不想名爲 「OperatingSystemId」的捕捉類型暴露的屬性。 「OperatingSystem」屬性超過 就足夠了。

  2. 我不想捕捉OperatingSystem的類型之間的雙向關係。只有一個單向關係 從捕獲OperatingSystem是必要的。

  3. 我不想名爲「CaptureId」的工作 系統表在數據庫中創建一個列。我甚至不知道爲什麼這是 要求,但我讀了一篇文章建議做到這一點, 的方式。

  4. 生成的SQL連接應該是一個INNER JOIN,而不是一個OUTER JOIN。

  5. 我真的需要在 Capture類型上將OperatingSystem屬性定義爲虛擬嗎?我不希望這個屬性是懶惰 加載。

  6. 加分指向某人,可以向我解釋這個例外,因爲 我完全失去了。谷歌搜索對於Fluent API來說是無望的。我 得到很多點擊,如果我使用的設計師,但我認爲這是 不相關,因爲所有的結果建議重新生成模型, ,我不認爲適用於此。

更新: 我也許並不清楚這件事。我已經在SQL Server中設置了數據庫模型。我想了解如何使用設計器爲現有數據庫模型使用Fluent API配置EF上下文而不使用。我明白,如果我使用設計器,我可以簡單地讓它從數據庫中生成我的上下文。這不是我想要的。對於那些很好奇的人,爲什麼 - 因爲我想了解如何使用Fluent API來做到這一點。

UPDATE2: 所以,看起來像什麼我已經建立了,EF是,如果我的查詢我指定的導航屬性過濾器生成正確連接。如果不這樣做,查詢中不會生成連接。無論如何,導航屬性仍然​​沒有被填充!

非常感謝你。

+0

你禁用約定嗎? –

+0

@Sidharth - 不,我不是。你建議我禁用哪些約定? – 9ee1

+0

您不需要禁用任何約定。見下面的答案 –

回答

10

因此,如果您還沒有像我一樣使用ORM,並且來自使用MyBatis等類似數據映射器的背景,解決方案就是這樣,給出我的問題中的示例。

首先,你需要不能宣佈你的實體類型爲密封和參加社團的任何屬性必須被聲明爲虛擬。這是因爲EF會在運行時用動態代理擴展型,也有動態代理重寫你的財產,使延遲加載:

public class Capture { 
    /// <summary> 
    /// Get and Set Capture's Unique Identifier. 
    /// </summary> 
    public int Id { get; set; } 

    /// <summary> 
    /// Get and Set Capture's Operating System. 
    /// </summary> 
    public virtual OperatingSystem OperatingSystem { get; set; } 
} 

public class OperatingSystem { 
    /// <summary> 
    /// Operating System's Unique Identifier. 
    /// </summary> 
    public int Id { get; set; } 
} 

如果你不這樣做,不會引發錯誤,但EF會始終將您的關聯屬性設置爲空。其次,除非您的關聯屬性尚未配置爲映射,否則不要將其映射到特定的表,因爲EF會抱怨同一個表基本上映射了兩次。在我的例子,我已經映射到其自身的OperatingSystem的類型和設置關聯時,我又被它映射:最後

internal sealed class EntityCaptureConfiguration : EntityTypeConfiguration<Capture> { 
    /// <summary> 
    /// Create an Entity Capture Configuration. 
    /// </summary> 
    public EntityCaptureConfiguration() { 
     this.ToTable("Capture"); 
     this.HasKey(m => m.Id); 

     this.Property(m => m.Id).HasColumnName("Id"); 

     this.HasRequired(m => m.OperatingSystem).WithRequiredDependent().Map(m => m.MapKey("OperatingSystemId")); 
    } 
} 

,如果你一定要絕對的密封,並宣佈你的實體類型你不想把任何屬性聲明爲虛擬的 - 你不能在無論如何密封類型 - 在上下文的配置,禁用代理和延遲加載:

​​

這是所有鄉親。我希望這能幫助像我這樣的人。