C# 如何从新创建的分离实体更新实体
假设我创建了一个新产品,如下所示:C# 如何从新创建的分离实体更新实体,c#,.net,linq-to-sql,C#,.net,Linq To Sql,假设我创建了一个新产品,如下所示: Product p=new Product(){ Id= 2,Name="some name"}; 我的产品变量从未附加到数据上下文,如何附加此实体,以便数据库中Id=2的现有产品使用我分离的产品的名称进行更新?我希望类似的方法也能奏效 Datacontext db = new Datacontext(); // replace with your DataContext Product originalProduct = db.Pr
Product p=new Product(){ Id= 2,Name="some name"};
我的产品变量从未附加到数据上下文,如何附加此实体,以便数据库中Id=2的现有产品使用我分离的产品的名称进行更新?我希望类似的方法也能奏效
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
更简单的解决方案是在您希望这样工作的实体上实现
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();
编辑:
我在工作中遇到了同样的问题,到目前为止,我找到的最优雅的解决方案是构建一个扩展方法,该方法接收新创建的实体(在您的例子中是产品
),并将其属性(标识符除外)复制到从DataContext中提取的实体
我通过反射复制了所有属性,这样,如果我更新了实体,那么扩展方法仍然有效
希望这对你也有帮助
如果你能找到一个更优雅的方法来解决这个问题,我想听听:)再加上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()
那么您只需要执行以下操作:
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()
这肯定会起作用,但总是复制属性可能会很痛苦。在NHibernate中,他们有一个名为RETACH的构造,可以让您指定它是DB中的一个现有对象,我不确定L2S是否有这个。DB.originalProduct似乎不正确。。。当您将p.Clone()分配给originalProduct时,它将不再“附加”到上下文,因此它将不会被持久化。哦,您是对的,我没有完全考虑清楚。。。我会检查一下并试着修复它。我在工作中遇到了同样的问题,所以我需要想出一个好的解决方案,当我这样做的时候,我会解决它的!:)谢谢如果要跳过使用反射,还可以使用DataContext的MappingSource将值复制到新的克隆版本。这样,它只会复制特定于数据库的属性。另外,我认为您正在寻找DataContext.GetTable().Attach(原始,新)在这里。没问题!我将把我用作另一个答案的代码发布到您的答案上:)