2010-10-04 66 views
1

我正在嘗試在Linq中進行更新。更新LINQ中的對象

public myFunc(MyItem newItem) 
{ 
    using(var db = new myDataContext()) 
    { 
    var item = (from o in db.myTable where o.id == myId select o).First(); 
    item = newItem; 
    db.SubmitAllChanges(); 
    } 
} 

這不會更新對象,我猜item = newItem更改項目引用其他。如果我更改單個字段(item.Name = newItem.Name等),更改會反映出來,但是我不想將MyItem類的內容分散到多個位置以降低可維護性。有沒有辦法讓項目= newItem複製一個字段的字段的基礎?

此外,MyItem與另一個表有關係,我想將newItem中的從屬項更新爲item。 (FWIW,沒有增加或刪除,只是更新。)是否有標準化的過程?

感謝您的幫助。

回答

6

嘛,MyItem應該是一個局部類 - 所以你可以添加一個CopyPropertiesFrom方法MyItem,然後寫

item.CopyPropertiesFrom(newItem); 

,代替目前的分配。

順便說一句,你可能要考慮使用,而不是你當前查詢此:

var item = db.myTable.First(o => o.id == myId); 

只是使事情變得簡單一點比在這種情況下,查詢表達式:)

+0

在我看來,這是一個非常普遍的過程。沒有自動的方法來做到這一點? 順便說一句,在LINQ查詢很棒的提示。我一直都在做這種事情,而你的事情更加簡潔。毫無疑問,你的建議將會顯着影響我編寫代碼的方式......非常感謝。 – 2010-10-04 16:48:46

+0

@Mike:我不認爲它*特別*常見。通常情況下,如果你想更新一個實體批發,你會先取它,編輯它,然後重新連接。 – 2010-10-04 16:54:15

+0

這是一個有趣的評論,我在代碼中考慮過它。爲什麼我必須這樣做,是在客戶端使用JavaScript編輯項目,然後以JSON形式提交。在我的例子中,JSON被解碼並且該對象是「newItem」。 對此有沒有更好的方法? – 2010-10-04 18:05:45

4

您不能僅將newItem指定爲item。當您將newItem指定爲item時,它只是將項目指向內存中的新位置......它實際上並未更新實體上的任何內容。

你需要去通過,並指定每個單獨的屬性:從實體模型

using(var db = new myDataContext()) 
{ 
    var item = db.myTable.First(o => o.id == myId); 
    item.Prop1 = newItem.Prop1; 
    item.Prop2 = newItem.Prop2; 
    // etc 
} 

一個更好的選擇將是擴展部分類(如喬恩斯基特提到的),這使一個方法(因此你可以重新使用該代碼)。

0

給它同樣的密鑰,並做一個附加,然後提交更改....

+0

我試圖做一個附加,即: db.myTable.Attach(newItem); 但是,這會產生重複鍵錯誤。我是否必須先刪除該項目?這似乎有點落後? – 2010-10-04 16:44:25

2

我認爲你應該首先獲得對C#變量和引用的基本概念的一些理解。

C#中的類型分爲兩組:引用類型值類型。它們在許多方面不同,而複製和比較就是其中的一個方面。

值類型包括簡單類型,如int(注意:string不是一種值類型,儘管您可能會這樣認爲),枚舉和結構。當您重新分配值不同的變量,他們被複制,將它們作爲參數等

按說

int x = 5; 
int y = 7; 
x = y; 

您指定的yx,導致x等於7
但是,如果你改變y進一步,x不會得到更新:

int x = 5; 
int y = 7; 
x = y; // 7 
y = 10; // x is still 7 

相反,引用類型沒有得到關於轉讓複製。它只是被複制的引用。

MyItem john = new Customer("John"); 
MyItem jack = new Customer("Jack"); 
jack = john; // now both references point to the same Customer 

在此代碼段中,我們忘記Customer稱爲"Jack"兩者jackjohn現在都指向同一個對象與名稱"John"

因此,說

item = newItem; 

你只能讓item點(或空如果它是空的),在那一刻被newItem引用的對象。

您可能要定義在類的Assign方法,執行任務的例行:

public void Assign(MyItem that) 
{ 
    this.Name = that.Name; 
    this.City = that.City; 

    // etc 
} 

在某些時候,你可能還需要編寫使用反射來分配所有的公共屬性的擴展方法 - 但對於另一個問題,這是一個很好的話題(最有可能已經被問及幾次回答)。

0

另一種選擇是使用AutoMapper自動複製 你的值。

上面說過,在很多情況下,在一個部分類中的簡單方法可以做得很好(就像Jon Skeet的答案一樣)。