我们的数据库中有一个审计表,在更新时,旧值和新值被序列化为XML并存储在同一行中。这些对象目前是深度克隆的,因此:
public EntityObject CloneEntity(EntityObject obj)
{
DataContractSerializer dcSer = new DataContractSerializer(obj.GetType());
MemoryStream memoryStream = new MemoryStream();
dcSer.WriteObject(memoryStream, obj);
memoryStream.Position = 0;
EntityObject newObject = (EntityObject)dcSer.ReadObject(memoryStream);
return newObject;
}虽然这种方法有效,但由于从深度克隆中提取的相关记录,它会生成大量数据,从dcSer.WriteObject(memoryStream, obj)上的数据库读取数十万次,最终的MemoryStream大小约为200MB,更不用说写回数据库的数据量了。不是很理想。
因此,我想做一个成员级克隆,因为我的理解是,成员级克隆会忽略对象引用,并避免复制所有相关的实体框架模型。
所以我这样做了:
public EntityObject CloneEntity(EntityObject obj)
{
EntityObjectAuditable auditable = (EntityObjectAuditable)obj; // invalid cast exception
return auditable.ShallowCopy();
}
// ....
public class EntityObjectAuditable : EntityObject
{
public EntityObjectAuditable ShallowCopy()
{
return (EntityObjectAuditable)this.MemberwiseClone();
}
}但是我得到了一个无效的强制转换异常,因为传入的EntityObject的实际类型是与表本身相关的子类。
我还尝试使用扩展方法访问MemberwiseClone(),但扩展方法不能访问受保护的方法。
那么,如何创建通用EntityObject的浅层副本呢?
发布于 2012-03-14 11:30:50
我的第一个建议是尝试一下,这与你现在做的类似,但对我来说效果很好,开销很小:
DataContractSerializationUtils.SerializeToXmlString(Entity, throwExceptions);而且,我以前已经成功地使用过这种方法,不会发现输出太过冗长。这看起来和你现在做的几乎一样。
/// <summary>
/// Creates an exact duplicate of the entity provided
/// </summary>
/// <param name="source">The source copy of the entity</param>
/// <returns>An exact duplicate entity</returns>
public TEntity Clone(TEntity Source)
{
// Don’t serialize a null object, simply return the default for that object
if (ReferenceEquals(Source, null))
{
return default(TEntity);
}
var dcs = new DataContractSerializer(typeof (TEntity));
using (Stream stream = new MemoryStream())
{
dcs.WriteObject(stream, Source);
stream.Seek(0, SeekOrigin.Begin);
return (TEntity) dcs.ReadObject(stream);
}
}如果这些选项看起来都不吸引人,我的建议是编写一个简短的函数,使用反射从源实体复制任何属性。
发布于 2012-10-11 08:23:46
发自:
http://www.codeproject.com/Tips/474296/Clone-an-Entity-in-Entity-Framework-4。
它比序列化更有效、更快--这正是你想要的!基本上,它使用反射将必要的属性复制到相同类型的新EntityObject中,并且能够通过使用泛型在从EntityObject派生的任何类上执行此操作。
public static T CopyEntity<T>(MyContext ctx, T entity, bool copyKeys = false) where T : EntityObject
{
T clone = ctx.CreateObject<T>();
PropertyInfo[] pis = entity.GetType().GetProperties();
foreach (PropertyInfo pi in pis)
{
EdmScalarPropertyAttribute[] attrs = (EdmScalarPropertyAttribute[])pi.GetCustomAttributes(typeof(EdmScalarPropertyAttribute), false);
foreach (EdmScalarPropertyAttribute attr in attrs)
{
if (!copyKeys && attr.EntityKeyProperty)
continue;
pi.SetValue(clone, pi.GetValue(entity, null), null);
}
}
return clone;
}例如,假设您有一个实体: Customer,它具有导航属性: Orders。然后,您可以使用上述方法复制客户及其订单,如下所示:
Customer newCustomer = CopyEntity(myObjectContext, myCustomer, false);
foreach(Order order in myCustomer.Orders)
{
Order newOrder = CopyEntity(myObjectContext, order, true);
newCustomer.Orders.Add(newOrder);
}发布于 2018-03-28 22:28:41
EF6中的CurrentValues.ToObject()怎么样?
var shallowCopy = (TEntity)_dbContext.Entry(entity).CurrentValues.ToObject();https://stackoverflow.com/questions/9695420
复制相似问题