将一个对象的属性复制到另一个对象

时间:2012-10-16 13:32:49

标签: c# linq reflection entity-framework-4

相关:Set Properties that not null using linq and reflection

嗨专家

我更改了上面链接中的代码:

public static void MyCopy<T>(this T src, T dest)
{
    var notNullProps = typeof(T).GetProperties()
                                .Where(x => x.GetValue(src, null) != null);

    foreach (var p in notNullProps)
    {
        p.SetValue(dest, p.GetValue(src, null),null);
    }
} 

我写了这段代码来复制peroperties:

NorthwindModel1.Order ord1 = new NorthwindModel1.Order() {CustomerID="Nima",Freight=1.33m,ShipCity="Agha" };
NorthwindModel1.Order ord2 = new NorthwindModel1.Order() ;

ord1.MyCopy(ord2);

但是我收到了这个错误:

  

EntityReference已经初始化。 InitializeRelatedReference仅应用于在实体对象的反序列化期间初始化新的EntityReference。

请帮我解决这个问题

1 个答案:

答案 0 :(得分:3)

正如评论中所提到的,你的反思代码不是问题,而是(正如异常消息明确告诉的那样)你间接触发了一个实体引用的重置。我的建议是双重的:要么修改你的反射代码只能复制标量属性(字符串,日期等等) - 或者忽略引用和集合 - 或者使用序列化:

public static T CloneBySerialization<T>(this T source) where T : EntityObject {
    var serializer = new DataContractSerializer(typeof(T));
    using (var ios = new MemoryStream()) {
        serializer.WriteObject(ios, source);
        ios.Seek(0, SeekOrigin.Begin);
        return ((T) serializer.ReadObject(ios));
    }
}

我必须警告你,通过这种方法,你将得到完整的对象图或引用。如果克隆的对象是实体,您将无法使用它/将其附加到另一个上下文,因为引用和外键也已被复制,“逐字”,这一切都可能导致冲突。如果您在密钥中使用标识列,问题会变得更糟。

我在以前关于这些问题的工作中做了很多魔术,就克隆而言,上面的代码就是你所需要的。全部,真的。

但是,要修复上下文问题和克隆实体的可用性,您必须清除引用,并假设您还在使用“root”实体¹↔*方向关系图(我希望我远程清楚,因为故事很长)以下也是必要的。

public static void ClearReferences(this EntityObject entity) {
    if (entity == null)
        return;

    foreach (var p in entity.GetType().GetProperties()) {
        if (p.PropertyType.IsGenericType) {

            var propertyType = p.PropertyType.GetGenericTypeDefinition();

            if (propertyType == typeof(EntityReference<>)) {
                var reference = p.GetValue(entity) as dynamic;
                if (reference.EntityKey != null) {
                    reference.EntityKey = null;
                    ((EntityObject) reference.Value).ClearReferences();
                }
            }

            if (propertyType == typeof(EntityCollection<>)) {
                var children = (p.GetValue(entity) as IEnumerable<EntityObject>).ToList(); // covariance
                foreach (var child in children)
                    child.ClearReferences();
            }
        }
    }
}

所以我的想法是你首先克隆(通过序列化/反序列化),然后你“净化”。