2013-08-27 40 views
0

我有一個問題,我只是無法通過谷歌解決或在stackoverflow上搜索。EF HasOptional WithMany

我有兩張表JournalLines和帳戶,我想引用一個帳戶在一個journalline(我討厭經濟學),但參考必須是可選的,帳戶有任何導航屬性到JournalLine(理想情況下)。

JournalLine:

public class JournalLine : Entity<int> 
{ 
    public int? Account_Id { get; set; } 
    public string Desc { get; set; } 
    public decimal Credit { get; set; } 
    public decimal Debit { get; set; } 
    public virtual Account Account { get; set; } 
} 

_account:

public class Account : Entity<int> 
{ 
    public string Accid { get; set; } 
    public string Desc { get; set; } 
    public int VatcodeId { get; set; } 
} 

和相應的映射:

public class JournalLineMap : EntityTypeConfiguration<JournalLine> 
{ 
    public JournalLineMap() 
    { 
     HasKey(k => new { k.Id, k.Account_Id }); 
     Property(k => k.Id) 
      .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 

     ToTable("attJournalLines"); 
     HasEntitySetName("JournalLines"); 

     HasOptional(jl => jl.Account) 
      .WithMany() 
      .HasForeignKey(jl => jl.Account_Id); 
    } 
} 

public class AccountMap : EntityTypeConfiguration<Account> 
{ 
    public AccountMap() 
    { 
     ToTable("attAccounts"); 
     HasEntitySetName("Accounts"); 
    } 
} 

錯誤IM得到的是這樣的:

tSystem.Data.Entity.Edm.EdmAssociationType:模型生成過程中檢測到

一個或多個驗證錯誤:在關係的參考>約束在角色「JournalLine_Account_Target」多重衝突'JournalLine_Account'。 >因爲從屬角色中的所有屬性都是不可空的,所以>主體角色的多重性必須爲'1'。

這使我困惑,我希望有人能夠解決這個問題。

更新

感謝您的答案它幫助我在路上和我有關係通過刪除鍵工作。然後,我在將Account分配給JournalLine時創建了一個奇怪的行爲,創建了重複帳戶。事實證明,這不是這樣奇怪的行爲,因爲我使用依賴注入的Repository模式。我沒有想到的是,這兩個存儲庫中的上下文並不相同,所以JournalLinesRepository不會跟蹤我從自己的存儲庫中獲取的帳戶,因此認爲只需將其作爲新實體插入即可。這是通過在存儲庫中注入相同的上下文來解決的,以便項目跟蹤按預期工作。再次感謝您的幫助。

+0

什麼是實體?也許我已經過時了EF - 它是框架的一部分,還是它是一個自定義的基類,其中是Id屬性? – STW

+0

這是正確的,它只是一個自定義的基類,它指定了Id列的類型。在某些情況下有點多餘,但在其他 – Patrik

回答

3

Ohlin's Answer正確地標識了問題 - 您不能擁有帶空列的複合主鍵。這引發了一些關於你想要建模的問題。

除了主鍵以外,看起來你的模型會起作用。事實上,我認爲只是刪除HasKey(k => new { k.Id, k.Account_Id });將使事情工作。如果你這樣做,那麼每個JournalLine都將擁有自己的唯一ID,並且可以選擇與Account相關。

這將導致諸如數據:

| AccountId | Desc   | 
| 123456789 | Some Account | 

| JournalId | AccountId | Description | Credit | Debit | 
|   1 |  null |  Some Tx | 100.00 | 0.0 | 
|   2 | 123456789 | Another Tx | 0.0 | 50.0 | 
|   3 | 123456789 |  MoreTx | 10.00 | 0.0 | 

在另一方面,如果你的理由在您的JournalLine鍵具有AccountId是暗示每個帳戶實際上有自己的日記(這聽起來隱約熟悉我的賬戶類),那麼你的建模需要一些調整 - 或者你可能需要一個特殊的「未分類」賬戶專門處理不適用於特定賬戶的交易。

+0

這幾乎按預期工作,除了在我添加到一行的帳戶的帳戶表中獲取重複行。 – Patrik

+0

要爲現有帳戶創建新的JournalLines,您應該首先檢索帳戶(像'context.Accounts.SingleOrDefault(acct => acct.Id == someAccountId)')。 – STW

+0

多數民衆贊成即時做到這一點。但是,當我保存它在表中創建一個新的帳戶任何想法爲什麼? – Patrik

3

通過查看您的代碼,它「感覺」像HasKey(k => new { k.Id, k.Account_Id });可能導致問題,因爲Account_Id是可空的,通常不被接受爲關鍵。嘗試刪除Account_Id的可空標誌來查看會發生什麼。

編輯:鑰匙在EF

的關鍵始終必須是唯一的,在它的組合(如果你有幾個列和鍵)。這是爲什麼你不能在關鍵參數中允許空值的基本原則。

當您將它指定爲外鍵時,您已經爲Account_Id添加了一個鍵,爲什麼還要將它作爲主鍵?特別是因爲你允許它爲空?

+0

有用我相信這是正確的;更好地理解預期的關係將會有所幫助。如果JournalLines偶爾通過帳戶鍵入,那麼它意味着帳戶是父帳戶 – STW

+0

我已經添加了一些到我的問題,但基本上我不明白爲什麼你想Account_Id作爲主鍵。而且您沒有從帳戶到JournalLines的參考,因此它們不能從帳戶中鍵入。 – Ohlin

+0

也許這樣做的目的是有效地創建一個Journal-Per-Account,這就是多少個會計分類帳(如果我記得的話) – STW