0

関連 : linq とリフレクションを使用して null でないプロパティを設定する

こんにちは専門家

上記のリンクのコードを変更します。

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 を初期化するためにのみ使用する必要があります。

この問題を解決するのを手伝ってください

4

1 に答える 1

3

コメントで述べたように、反射コードは問題ではありませんが、(例外メッセージが明示的に示すように) エンティティ参照の 1 つのリセットを間接的にトリガーしているという事実です。私のアドバイスは2つあります。リフレクションコードを変更して、スカラープロパティ(文字列、日付など)のみをコピーするか、参照とコレクションを無視するか、シリアル化を使用します。

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

このアプローチでは、完全なオブジェクト グラフまたは参照になってしまうことに注意してください。複製されたオブジェクトがエンティティである場合、参照と外部キーも「逐語的に」コピーされているため、それを使用したり別のコンテキストにアタッチしたりすることはできず、これはすべて競合につながる可能性があります。キーでID列を使用している場合、問題はさらに悪化します。

私はこれらの問題に関して以前の仕事で多くの魔法を使いました。クローンに関する限り、必要なのは上記のコードだけです。すべて、本当に。

ただし、コンテキストの問題と複製されたエンティティの使いやすさを修正するには、参照をクリアし、¹ ↔ * 方向リレーショナル グラフの「ルート」エンティティも操作しているという前提の下で行う必要があります (話が長いので少しはっきりしています)以下も必要になります。

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 に答える