2016-05-27 37 views
0

我有3個實體它們中的哪一個有一個FK到另一個者(可選)實體框架定義的ForeignKey一個到幾個實體1〜1..0

class Person 
{ 
    public int id {get;set;} 

    public int? logid {get;set;} 
    [ForeignKey("logid") 
    public TaskLog Log{get;set;} 
} 

class Product 
{ 
    public int id {get;set;} 

    public int? logid {get;set;} 
    [ForeignKey("logid") 
    public TaskLog Log{get;set;} 
} 

class TaskLog 
{ 
    public int id {get;set;} 
    public int? refid {get;set;} //will be fk for Person and Product 
    public Person Person {get;set;} 
    public Product Product {get;set;} 
} 

有的FluentApi用於級聯和關係

modelBuilder.Entity<TaskLog>() 
      .HasOptional(i => i.Person).WithMany().HasForeignKey(i => i.refid).WillCascadeOnDelete(true); 

modelBuilder.Entity<Person>() 
      .HasOptional(i => i.TaskLog).WithMany().HasForeignKey(i => i.logid).WillCascadeOnDelete(false); 

modelBuilder.Entity<TaskLog>() 
      .HasOptional(i => i.Product).WithMany().HasForeignKey(i => i.refid).WillCascadeOnDelete(true); 

modelBuilder.Entity<Product>() 
      .HasOptional(i => i.TaskLog).WithMany().HasForeignKey(i => i.logid).WillCascadeOnDelete(false); 

上述實體已正確遷移到數據庫,沒有任何其他字段。

但問題是,當我想爲現有Person創造新TaskLog:發生

var person = PersonManager.loadById(1); 
person.Log = new TaskLog() { ... }; 
personManager.SaveChanges(); 

以下錯誤,這意味着它往裏Product爲相同的ID(同個人ID),並因爲有不是任何產品,所以它不能添加新的TaskLog,因爲它與產品也有可選的關係。

INSERT語句與FOREIGN KEY約束「FK_dbo.TaskLog_dbo.Product_refid」衝突。
數據庫「database1」發生衝突,表「dbo.Product」,列'id'。
該聲明已被終止。

所以我想在TaskLog實體中有一個字段,它將用作產品和人員(以及更多)的參考,但不在一起。

一個TaskLog可能適用於一個人,也可能適用於一個產品或不適用於他們,但不適用於他們兩個。

請注意,我想要那個refid,我知道可以使用InverseProperty並從TaskLog中刪除refid。
編輯:
請張貼不refid解決方案,如果你確信refid是問題,你可以解決TaskLog無需額外的現場上述關係。
Person-TaskLog並且還Product-TaskLog之間由一個FK在任務日誌或不任務日誌任何附加字段1到1..0關係

+0

你確定這種方法應該工作嗎?我建議將2個單獨的字段作爲人員和產品的外鍵。 –

+0

由於有超過5個與TaskLog相關的實體,因此每個實體添加FK並不是一個好的解決方案。如果你有沒有refid的解決方案,我可以忽略它。 – Hamid

+0

我想從'TaskLog'訪問Person或Product,並且還可以從Person和Product訪問'TaskLog',而無需在'TaskLog'中聲明單獨的字段爲Product和Person,因爲有幾個像它們一樣的實體應該分配給'TaskLog' – Hamid

回答

0

SQL服務器實際上允許創建外鍵的由其中一個數據庫字段指的是兩個主鍵。這是數據庫的一部分創建腳本:

ALTER TABLE [dbo].[TaskLogs] ADD CONSTRAINT [FK_dbo.TaskLogs_dbo.People_refid] 
    FOREIGN KEY ([refid]) REFERENCES [dbo].[People] ([id]) ON DELETE CASCADE 
ALTER TABLE [dbo].[TaskLogs] ADD CONSTRAINT [FK_dbo.TaskLogs_dbo.Products_refid] 
    FOREIGN KEY ([refid]) REFERENCES [dbo].[Products] ([id]) ON DELETE CASCADE 

所以refid兩個點PeopleProducts。那麼,只有一種方法可以同時滿足FK約束:將TaskLogrefid相加,其對應於Person a Product

對於新的TaskLog,您只有Person而不是Product,因此違反了FK。並且如果您也有匹配的Product,那麼Personproduct都必須具有相同的TaskLog。那真的是你想要的嗎?

如果不是,您可以堅持只有一個refid的解決方案,但它根本不可能。

+0

不,我沒有,正如你所說,沒有任何一個簡單的解決方案''refid',所以我添加了一個額外的字段到'TaskLog',它是'discriminator'和'refid'和'discriminator'我把'TaskLog'和幾個實體之間的關係以及其他實體與'TaskLog'之間的關係聯繫起來 – Hamid

+0

然後在數據庫中沒有硬外鍵的情況下,你有所謂的*多態關聯*。 –