2013-10-21 53 views
0

我已經這是向服務器發送一個請求以下對象進行交鋒到數據庫的導航屬性:添加到數據庫中的實體已存在

var foo = new Foo 
{ 
    Id = 0, 
    Name = "Foo", 
    Bar = new Bar 
    { 
     Id = 1, 
     Name = "Bar" 
    } 
} 

foo需要被添加到數據庫。數據庫中可能已經存在Bar,所以如果存在,則不應再次添加。如果我剛剛收到的Bar是從一個數據庫中的不同(即Name是不同的),那麼應該將數據庫更新,以反映新的Bar

我曾嘗試下面的代碼片段,和他們不工作:

void Insert (Foo foo) 
{ 
    var bar = context.bars.FirstOrDefault(x => x.Id == Foo.Bar.Id) 
    if (bar != null) 
    { 
     context.bars.attach(foo.Bar) 

     // doesn't work because the search 
     //I just preformed already bound an object 
     //with this ID to the context, 
     //and I can't attach another with the same ID. 
     //Should I somehow "detach" the bar 
     //that I got from the search result first? 
    } 
    context.Foo.add(foo) 
} 

void Insert (Foo foo) 
{ 
    var bar = context.bars.FirstOrDefault(x => x.Id == Foo.Bar.Id) 
    if (bar != null) 
    { 
     bar = foo.Bar 

     // successfully updates the object in the Database, 
     // But does not stop the insert below from 
     // trying to add it again, throwing a SQL Error 
     // for violating the PRIMARY KEY constraint. 
    } 
    context.Foo.add(foo) 
} 

我錯過了什麼嗎?我覺得做這樣的事情不應該很難。

+0

這篇文章將對象圖可以幫助的陷阱http://msdn.microsoft.com/en-us/magazine/dn166926.aspx – Colin

+0

投票合併斷開對象圖在這裏:https://entityframework.codeplex.com/discussions/432661 – Colin

回答

2

你的第二個部分是接近直角的,你實際上並沒有更新foo.Bar雖然這就是爲什麼我認爲它試圖創建一個新的,嘗試

var bar = context.bars.FirstOrDefault(x => x.Id == Foo.Bar.Id); 
if (bar != null) 
{ 
    bar.Name = foo.Bar.Name; 
    foo.Bar = bar; 
} 
context.Foo.add(foo); 
+0

真的沒有更通用的方法來做到這一點比手動映射屬性?看起來會讓重構變成一種痛苦。 – JHixson

+0

那麼有[映射](https://github.com/AutoMapper/AutoMapper)庫,使這種東西你的生活更輕鬆。但是,他們對問題的範圍有所瞭解。另外,你可以試着弄清實體的內部屬性,例如[使用實體鍵](http://msdn.microsoft.com/en-us/library/vstudio/dd283139(v = vs.100).aspx),嘗試*使用新的替換*現有的..我認爲手動映射更安全。絕對; – James

+0

絕對;我的項目中已經有了Automapper,所以使用它就好了。我只是認爲會有更多的「內置」方式來做到這一點。只要把它放在我的代碼中,就像一個魅力! – JHixson

相關問題