【问题标题】:Copy Properties of one object to another object将一个对象的属性复制到另一个对象
【发布时间】:2012-10-17 00:34:11
【问题描述】:

相关: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);
    }
} 

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

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。

请帮我解决这个问题

【问题讨论】:

  • 查看此页面上的内容/cmets:urmanet.ch/?p=11 此错误似乎与外键引用有关。在评论中是一个可能的解决方案。该页面还描述了实体对象的克隆/复制,因此无论如何这对您来说可能是值得一读的。
  • 您是否尝试过使用 BinaryFormatter 进行克隆?

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


【解决方案1】:

正如 cmets 中所述,您的反射代码不是问题,而是(正如异常消息明确告知的那样)您间接触发了您的一个实体引用的重置这一事实。我的建议是双重的:要么修改你的反射代码,只复制 scalar 属性(字符串、日期等)——或者忽略引用和集合——或者使用序列化:

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-08
    • 2018-02-01
    • 2017-05-08
    • 1970-01-01
    • 1970-01-01
    • 2016-12-21
    相关资源
    最近更新 更多