我嘗試搜索SO,但是我發現的所有結果似乎都涉及更新已經保存到數據庫的實體的PK。我的情況不同。多個鏈接的1-1關係不按預期同步PK
我有一個數據庫中有1-0..1個關係的3個表。的關係是這樣的:
A <- B <- C
其中「< - 」代表的關係,並指出主要的結束。即每個B總是有一個相關的A,但一個A可以沒有B.換句話說,A的基數是1,B的是0..1。
每個關係都由從子實體的PK到父實體的PK的FK表示。每個PK是具有客戶端生成值的uniqueidentifier
Id
列。我已經從數據庫中生成了一個EF 4模型,它與相同的基數具有相同的關係。
我試圖將子實體B
和C
添加到現有的A
實體。由於設計原因,這兩個新實例是在代碼的和平下創建的,並且A
實體與另一個實體中的B
實體鏈接。此外,我不希望後者知道存在C
。
這裏的B
和C
創建代碼的樣子:
public B CreateB()
{
return new B
{
Id = Guid.NewGuid(),
C = new C(),
};
}
而現在的鏈接並保存代碼:
// a is an instance of A that has been loaded from DB
// and hence has a persistent Id value.
// b is a just-created instance of B
// that has a non-persistent Id value and null reference to A.
void SaveBlahBlahBlah(A a, B b)
{
// At this point b and c have the same Id value.
// It differs from a's Id, but that's expected, they haven't been linked yet.
b.A = a;
// At this point b receives a's Id value, but c keeps the original one,
// therefore the existing b-c link gets broken!
using(var ctx = new MyContext())
{
ctx.As.Attach(a); // This throws exception saying
// I've violated referential integrity.
// It doesn't say which relationship is broken,
// but I guess it's the B-C one since
// the debugger shows them to have different values if PKs
ctx.Bs.AddObject(b);
ctx.SaveChanges();
}
}
我已經試過這既與默認EF的代碼生成器(使用EF的Entity
類作爲生成實體的基類)以及自跟蹤實體代碼生成器。結果是一樣的。
因此,代碼崩潰。原因很可能是A
和B
已鏈接後,B
和C
獲得不同的PK值,這對於具有1-1關係的實體是非法的。
我期望的是C自動將它的PK同步到從A
實例獲得的值B
。這似乎是合理的,因爲我使用對象圖,我有一個現有的B
- C
關係,這是可以的,並且我希望鏈接B
和A
之後它仍然保持正常。爲什麼會突破?如果B
或C
存在於數據庫中並且我無法更改它們的PK,我會理解它。但情況並非如此,兩個實體都是剛創建的。
因爲EF要求1-1關係的雙方都是PK,所以我不能通過使用與FK的PK列分開來打破密鑰鏈。
我不想手動同步密鑰,因爲事實上有更多的1-1相關的表,這將需要同步代碼出現在很多地方。
我相信我將能夠更新STE生成器的T4模板,以將PK更新降級到1-1關係。但我對T4不太熟悉,不太樂意這樣做。
我有2個問題:
- 是我在我的情況下級聯PK更新的預期錯了因爲某些原因? (雖然看起來很奇怪)也就是說,它是一個錯誤還是一個特徵?
- 除修改STE模板之外是否還有其他解決問題的方法?也許在EF映射或上下文中有一些神奇的選項?
在此先感謝。
+1解釋得很清楚! – 2012-03-27 19:36:24
謝謝。我應該注意到我使用了'Attach',因爲沒有它,EF試圖插入'A',由於'A'已經存在於數據庫中,導致錯誤。從那時起,我改變了模型和風格(當時我使用了EFCF)。所以也許你的建議會奏效,我會試試看。 – 2012-03-28 01:45:18
您可以使用'Attach',但您需要在*與B建立關係之前進行此操作。* – 2012-03-28 02:25:55