2017-02-17 48 views
0

我試圖使用實體框架NullableGuid但是當我試圖提交我得到驗證的消息,由於外鍵是空的變化,我有以下領域類,DomainType類有孩子DomainCustomField: -實體框架與可空指引?導致驗證錯誤

DomainType.cs
public class DomainType 
{ 
    public Guid? Id 
    { 
     get; 
     set; 
    } 
    private IList<DomainCustomField> _domainCustomFields; 

    public string Name 
    { 
     get; 
     set; 
    } 

    public Guid? AccountId 
    { 
     get; 
     set; 
    } 

    public virtual IList<DomainCustomField> DomainCustomFields 
    { 
     get 
     { 
      return this._domainCustomFields; 
     } 
     set 
     { 
      this._domainCustomFields = value; 
     } 
    } 
} 

DomainCustomField.cs
public class DomainCustomField 
{ 
     public Guid? Id 
     { 
       get; 
       set; 
     } 
     public string Name 
     { 
      get; 
      set; 
     } 
     public Guid? DomainTypeId 
     { 
      get; 
      set; 
     } 
} 
下面

是映射: -

modelBuilder.Domain<DomainCustomField>().HasKey((DomainCustomField p) => new 
      { 
       p.Id, 
       p.DomainTypeId 
      }); 
      modelBuilder.Domain<DomainCustomField>() 
       .Property(p => p.Id) 
       .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 
      modelBuilder.Domain<DomainType>() 
       .HasMany(p => p.DomainCustomFields) 
       .WithRequired() 
       .HasForeignKey<Guid?>(x => x.DomainTypeId); 

下面是我嘗試插入的示例代碼。

DomainType domainType = new DomainType() 
     { 
      AccountId = customer.Id 
     }; 
     domainType.DomainCustomFields.Add(new DomainCustomField() 
     { 
      Name = "Test" 
     }); 
     Workspace.Add<DomainType>(domainType); 
     Workspace.CommitChanges(); 

錯誤: - 用於DomainTypeId驗證錯誤需要

在相同的代碼,如果我在ID變量正確地更改Guid?Guid然後其工作。我不知道如何處理nullableGuid。我是否需要在子引用中手動設置父鍵?那麼如何在Guid的情況下正常工作?

注意: - 我使用的是Guid,因爲我使用分佈式數據庫,其中id可以從多個源系統生成。 我使用Guid?,因爲默認Guid生成00000000-0000-0000-0000-000000000000爲空Guid它可以增加數據庫大小。

+0

您試過了(在模型中添加導航屬性'DomainType')'.HasOptional' - >'modelBuilder.Domain () .Property(p => p.Id) ..HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity).HasOptional(p => p.DomainType).. HasForeignKey(x => x.DomainTypeId)' – Developer

+0

是的,我試過HasOptional。它不是那個問題。即使它們被鏈接,它也不會在子變量中設置父ID。 –

+0

這個錯誤對我來說很合理,可能在這裏我完全錯了。當你的主鍵是「空的」(不知道「可空」主鍵是如何工作的)時,EF可能沒有爲子集合設置正確的關係(因爲父ID是空的)。 – Developer

回答

-1

您可以使用數據庫的標準標識符。 GUID?作爲字段存儲在表中。

+0

請看看問題中提到的註釋'默認Guid生成00000000-0000-0000-0000-000000000000爲可以增長數據庫大小的空Guid' –

+0

您不能爲主鍵使用可爲空的類型。主鍵和GUID使用整數類型?作爲表中的一個字段。 – npsavin

0

該問題與Guid類型無關(int也會發生這種情況),但是實體中使用的屬性類型的可空性與模型隱含的屬性的實際可空性之間存在差異。

首先,EF要求PK是非空的。因此,DomainType.Id,DomainCustomField.IdDomainCustomField.DomainTypeId實際上是不可修改的(目前還不清楚爲什麼你在DomainCustomField的PK中包含DomainTypeId,它已經有獨特的數據庫生成Id,但這是另一回事)。

其次,DomainCustomField.DomainTypeId實際上不可爲空,因爲您已指定--FK關係配置的WithRequired()部分。

現在,EF盡力處理這些差異。如果查看生成的遷移,您將看到所有相關字段的相應數據庫表列不可空。然而(沒有什麼是完美的,你知道)EF代碼的某些部分無法處理這種差異,因此也是例外。

就這麼說,始終保持模型屬性的可空性與其實際的可空性同步。在你的情況下,這兩個屬性是不可空的(即Guid類型)。

P.S.怎麼樣我使用Guid?因爲默認Guid生成00000000-0000-0000-0000-000000000000爲空Guid它可以增加數據庫大小。,我不知道你是什麼意思。類屬性的無關性與數據庫大小無關,正如我已經提到的那樣,這種設置的相應數據庫表列不能爲空。

另請注意,在您的示例中,您忘記設置新的DomainTypeId,您應該這樣做,因爲它不是自動生成的。

1

我會在我的回答中採取稍微不同的方法,並嘗試告訴你如何改變以獲得一個工作示例;

像有人指出的那樣,唯一標識符不能爲空,因此DomainType中的Id字段應爲Guid。您還需要更改DomainCustomField中的Id字段。這些可能需要一個空的構造函數才能創建一個新的Guid。其次,您的其他對象Guid? DomainTypeId中的外鍵非常好,這可以保留,但如果它處於停留狀態,您將需要更改您的配置。

在此塊中,您已指定該屬性是必需的?

modelBuilder.Domain<DomainType>() 
       .HasMany(p => p.DomainCustomFields) 
       .WithRequired() 
       .HasForeignKey<Guid?>(x => x.DomainTypeId); 

因此,簡單地說它是可選的;

modelBuilder.Domain<DomainType>() 
       .HasMany(p => p.DomainCustomFields) 
       .WithOptional() 
       .HasForeignKey<Guid?>(x => x.DomainTypeId); 

這應該可以解決您的問題。任何問題都讓我知道:)

+0

這是我今天的問題,我已經指定了Guid列作爲可選項,但沒有爲上面的許多行提示,提醒我將其設置爲WithOptional可以爲我解決這個問題。 如果我有WithRequired,那麼生成的sql將會很奇怪,並且它不會返回例如爲空的guid。 guid = null。即使數據庫有一些空的guid值,也會返回空列表。 – Andrew