2015-10-30 94 views
1

CLARIFICATION:我不是試圖在數據庫字段中存儲類/類型,或者使用類/類型本身作爲鍵值。我試圖使用類/類型(在這種情況下,Guid)的單個屬性作爲關鍵。實體框架6-將主鍵作爲類型的屬性

雖然我不認爲它與這個特定問題嚴格相關,但它可能對上下文有用:我試圖在我的最新項目中實現Semantic Types。我在我的代碼中取得了一些成功,並且事實上確定了幾個可能因此而不快速識別的錯誤。

在一些Fluent API代碼的幫助下,我的語義類型與EF6在非關鍵字字段中整合在一起。

但是,當試圖對關鍵字段使用語義類型時,EF會生成一個運行時異常,指出沒有定義的鍵 - 顯然存在。

用一個簡單的GUID作爲關鍵

這裏是我使用的EF實體不使用語義類型的例子:

public partial class MyEntity 
{ 
    [Key] 
    public Guid id { get; set; } 

    public string SomeData { get; set; } 
} 

上述工作正常。

與一類性質的關鍵 - 嘗試#1

現在,我定義了一個新的語義類型,如下所示:

public class MyEntityId: SemanticType<Guid> 
{ 
    public MyEntityId() 
     : base(IsValid, Guid.Empty) 
    { } 

    public MyEntityId(Guid value) 
     : base(IsValid, value) 
    { } 

    public static bool IsValid(Guid value) 
    { 
     return true; 
    } 
} 

...並相應地更新EF模型。

public partial class MyEntity 
{ 
    [Key] 
    public MyEntityId id { get; set; } 

    public string SomeData { get; set; } 
} 

我再添加一些代碼到的DbContext OnModelCreating方法將MyEntityId.Value映射到所需的列名:現在

modelBuilder 
    .Entity<MyEntity>() 
    .Property(x => x.MyEntityId.Value) 
    .HasColumnName("id"); 

,上述所有的編譯罰款。但只要與表交互,我會得到以下例外:

An exception of type 'System.Data.Entity.ModelConfiguration.ModelValidationException' 
occurred in EntityFramework.dll but was not handled in user code 

EntityType 'MyEntity' has no key defined. Define the key for this MyEntity. 

顯然,該實體確實有一個已定義的密鑰。

與一種類型的屬性作爲密鑰 - 嘗試#2

所以,我試圖消除從模型[鍵]屬性,並修改了流利API代碼,如下所示:

modelBuilder 
    .Entity<MyEntity>() 
    .HasKey(x => x.MyEntityId.Value); 
    .Property(x => x.MyEntityId.Value) 
    .HasColumnName("id") 

但是這個代碼將生成以下異常:

An exception of type 'System.InvalidOperationException' occurred in 
EntityFramework.dll but was not handled in user code 

Additional information: The properties expression 'x => x.MyEntityId.Value' 
is not valid. The expression should represent a property: 
C#: 't => t.MyProperty' VB.Net: 'Function(t) t.MyProperty'. 
When specifying multiple properties use an anonymous type: 
C#: 't => new { t.MyProperty1, t.MyProperty2 }' 
VB.Net: 'Function(t) New With { t.MyProperty1, t.MyProperty2 }'. 

與一類性質的關鍵 - 在誘惑#3

因此,在挖掘SO後,它看起來像EF需要一個屬性,而不僅僅是一個公共領域。所以我修改了語義類型引入一個新的「EFValue」屬性,如下所示:

public class MyEntityId: SemanticType<Guid> 
{ 
    public MyEntityId() 
     : base(IsValid, Guid.Empty) 
    { } 

    public MyEntityId(Guid value) 
     : base(IsValid, value) 
    { } 

    public static bool IsValid(Guid value) 
    { 
     return true; 
    } 

    public Guid EFValue 
    { 
     get { return Value; } 
    } 
} 

...並修改了流利的API代碼,如下所示:

modelBuilder 
    .Entity<MyEntity>() 
    .HasKey(x => x.MyEntityId.EFValue); 
    .Property(x => x.MyEntityId.Value) 
    .HasColumnName("id") 

但後來我得到的同樣的'System.InvalidOperationException'異常。

是不是可以像這樣定義類型的屬性作爲EF6中的主鍵?

+0

把自己當成關係數據庫管理系統,你如何處理類型作爲關鍵字?如果你可以期待EF做到這一點。 – dotctor

+0

即使你可以這樣做,你確定你想要嗎?想想看,如果EF必須序列化(很可能是二進制)表格的鍵,這將導致非常大且難以索引的鍵。鍵應該是簡單和可排序的,我不確定你通過將PK或FK改爲語義類型來獲得任何東西。 –

+0

我很努力地想知道爲什麼這是一個問題,tbh。我不是試圖使用類型作爲鍵 - 只是類型實例屬性的值 - 在這種情況下,數據庫表中的鍵仍然是GUID。類型本身有一個我想用作鍵的屬性。在我可能的無知中,我沒有看到使用Fluent API將屬性映射到列的區別:modelBuilder 。實體().Property(x => x.MyEntityId.Value)。 HasColumnName( 「ID」)。我顯然缺少一些東西。 – user2209634

回答

0

錯誤使它很清楚你不能做你想做的事。只需將實體級別的ID屬性包裝起來,它就可以工作:

public partial class MyEntity 
{ 
    public MyEntityId BadIdea { get; set; } 

    [Key] 
    public Guid Id 
    { 
     get 
     { 
      // needs null check 
      return BadIdea.Value; 
     } 
     set 
     { 
      // needs null check 
      BadIdea.Value = value; 
     } 
    } 
}