2010-03-01 81 views
1

比方說,我創建了這樣一個新的產品:如何更新由新創建脫離實體實體

Product p=new Product(){ Id= 2,Name="some name"}; 

我的產品變量從未被連接到數據上下文,我怎麼能把這個實體,以便我ID = 2的數據庫中的現有產品是否使用我分離的產品的名稱進行更新?

回答

0

我希望類似的東西會工作

Datacontext db = new Datacontext(); // replace with your DataContext 
Product originalProduct = 
     db.Products.Single(p => p.Id == 2); // get product with Id 2 

originalProduct.Name = "SomeName"; // only reset Name prop 
originalProduct = p;    // or you may assign p to originalProduct 
db.SubmitChanges();     // submit changes to DB 
+0

,無疑可以工作,但可能是痛苦的,始終在屬性複製。在NHibernate中,他們有一個名爲Reattach的構造,它可以讓你指定它是數據庫中的一個現有對象,我不確定L2S是否存在。 – 2010-03-01 20:03:12

+0

當然,但是op正在使用L2S – 2010-03-01 20:04:30

0

有點容易的解決辦法是落實你想這樣的工作的實體ICloneable接口。然後,您只需將Clone()調入您從數據庫中提取的「原始」實體。

例子:

class Product : ICloneable 
{ 
    public virtual int Id { get; private set; } 
    public virtual string Name { get; set; } 

    public object Clone() 
    { 
     return new Product() { Id=this.Id, Name=this.Name }; 
    } 
} 

然後所有你需要做的是:

Datacontext db = new Datacontext(); // replace with your DataContext 
Product originalProduct = 
     db.Products.Single(p => p.Id == 2); // get product with Id 2 

db.originalProduct = p.Clone() 
db.SubmitChanges(); 

編輯: 我跑進在工作中同樣的問題,迄今爲止最優雅的解決方案我找到的是建立一個擴展方法,接收新創建的實體,在你的情況Product,並將它的屬性(標識符除外)複製到你從DataContext中提取的實體。

我通過反射覆制了所有的屬性,這樣,如果我更新了實體,那麼我的擴展方法仍然可以工作。

希望這對你也有幫助。

如果你找到一個更優雅的解決這個問題,我想聽聽:)

+0

db.originalProduct看起來不正確...當您將p.Clone()分配給originalProduct時,它不再「附加」到上下文中,因此它不會被持久化。 – 2010-12-23 06:34:39

+0

哦,你是對的,我沒有完全想到它......我會檢查出來並嘗試修復它。我在工作中遇到了同樣的問題,所以我需要考慮一個好的解決方案,當我這樣做時,我會解決它! :) 謝謝! – gillyb 2010-12-23 09:07:28

+1

如果要跳過使用反射,還可以使用DataContext的MappingSource將值複製到新的克隆版本。這樣它只會複製特定於您的數據庫的屬性。 – rossisdead 2010-12-24 00:10:39

0

只是爲了添加到gillyb的帖子,我離開那裏的註釋。克隆你的實體一個非常簡單的方法是這樣:

Private Function CloneEntity(Of TEntity)(ByVal entity As TEntity) As TEntity 

    Dim dataContext As New DataContext() 
    Dim entityType As System.Type = GetType(TEntity) 

    ' If the purpose of the clone is just to attach it the existing entity to a new 
    ' DataContext, you can use IdentityMembers in place of PersistantDataMembers. Setting 
    ' only the IdentityMembers is enough to allow for attaching the clone as an "originaL" 
    ' entity to the DataContext. 
    Dim dataMembers = dataContext.Mapping.GetTable(entityType).RowType.PersistentDataMembers 

    Dim clone As TEntity ' Do something here to create an entity of the desired type. 
    Dim boxedClone As Object = clone 

    For Each dm In dataMembers 

     ' Depending on how your ColumnAttribute is set, you would use StorageAccessor if 
     ' the Storage property is set. Otherwise, you would use MemberAccessor instead. 
      dm.StorageAccessor.SetBoxedValue(boxedClone, dm.StorageAccessor.GetBoxedValue(entity)) 
    Next 

    Return clone 

End Function 

然後你只需要做到這一點:

Dim dataContext As New DataContext() 
dataContext.GetTable(Of Object)().Attach(entityToUpdate, CloneEntity(entityToUpdate)) 
dataContext.SubmitChanges()