0

涉及:使用 linq 和反射设置不为空的属性

嗨专家

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

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);
    }
} 

我写了这段代码来复制属性:

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。

请帮我解决这个问题

4

1 回答 1

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));
    }
}

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

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

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

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();
            }
        }
    }
}

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

于 2012-10-16T16:28:26.360 回答