1

我有一個POCO A實體引用B實體,比如說b。我想A引用一個不同的B實體,比如說bb不同的現有實體的外鍵在更新引用實體時沒有被保存

這些步驟:

var b = // get existing b from somewhere out-of-context 
var a = new A { B = b } 
dbcontext.Set<B>.Attach(a.B); 
dbcontext.Set<A>.Add(a); 
context.SaveChanges(); 

產生a的INSERT語句與正確設置爲b主鍵ID的B_ID外鍵的預期。這些後續步驟:

var bb = // get existing bb from somewhere out-of-context 
a.B = bb; 
differentdbcontext.Set<B>.Attach(a.B); 
differentdbcontext.Set<A>.Attach(a); 
differentdbcontext.Entry(a).State = EntityState.Modified; 
differentdbcontext.SaveChanges(); 

導致持久數據無變化。如預期的那樣,更新語句不包括set B_ID = ...

我正在做一些簡單的錯誤,因爲我已經有過類似以前的其他場景。

回答

1

將狀態設置爲Modified只對標量屬性有影響,但不影響導航屬性。我假設B_ID不是您模型中的屬性,但只有數據庫中的外鍵列不會暴露給您的模型。

在這種情況下,您只能通過利用實體框架的自動更改檢測來更新關係。一種方法 - 我會調用這個標準方法 - 是加載原始A包括B從數據庫,設置a.B到新bb,然後保存更改:

var bb = // get existing bb from somewhere out-of-context 

differentdbcontext.Set<B>().Attach(bb); 
differentdbcontext.Set<A>().Include(x => x.B).Single(x => x.Id == a.Id); 

a.B = bb; 

differentdbcontext.SaveChanges(); 

如果你不不想從DB加載原始的一些技巧編程是必需的:

var bb = // get existing bb from somewhere out-of-context 

if ( (a.B == null && bb != null) 
    || (a.B != null && bb == null) 
    || (a.B != null && bb != null && a.B.Id != bb.Id)) //take care not to attach 
                 //two objects with same key 
{ 
    if (bb != null) 
     differentdbcontext.Set<B>().Attach(bb); 
    differentdbcontext.Set<A>().Attach(a); 
    a.B = bb; // EF will detect this change 
} 
else if (a.B == null && bb == null) 
{ 
    // create a dummy a.B 
    a.B = new B(); // it doesn't matter which Id 
    differentdbcontext.Set<A>().Attach(a); 
    a.B = bb; // = null -> EF will detect a change 
} 

differentdbcontext.SaveChanges(); 

或類似的。我們的想法是在附加對象後更改引用,以便更改檢測將FK列的更新發送到數據庫。

將外鍵作爲屬性暴露到模型中會使這種情況更容易。將狀態設置爲Modified會有效,因爲FK屬性是標量。

+0

我應該澄清一下,在客戶端發送'A'DTO的反序列化時,'A.B'被設置爲'bb'。因此,在使用'differentdbcontext'之前,沒有真正的賦值給'A.B'。有沒有一種明確的方式告訴EF *:*屬性在沒有做任務的情況下改變了? – Kit

+0

@Kit:不,沒有。明確告知EF屬性已更改只支持標量屬性和複雜屬性,而不支持導航屬性/關係。這是獨立協會(=無外鍵屬性)的弱點之一,也是EF 4引入FK關聯(=暴露外鍵)的主要原因。 – Slauma

+0

接受了答案,因爲它基本上是正確的,但我不能相信我將不得不通過EF來通過一個通用的存儲庫接口來完成這項工作。 – Kit

相關問題