4

私は最近EntityFramework1.0を使い始めたばかりで、誰もが話している苦痛を感じ始めていると思います。ベストプラクティスを使用しようとしているので、AutoMapperを介してエンティティとの間でマッピングされる一連のDTOがあります。

本当の問題は、オブジェクトを更新しようとしているときです。最初の落とし穴は、新しいエンティティを作成し、DTOからデータを転送し、それでもエンティティObjectContextに変更されたことを認識させる方法が見つからなかったことです。次のコードを使用しました。

public VideoDTO UpdateVideo(VideoDTO pVideo)
        {
            Video video = new Video();
            Mapper.Map(pVideo, video);
            context.Attach(video); //Successfully attaches
            context.ApplyPropertyChanges("Videos", video);  // no changes made as far as entity knows b/c it was attached in it's updated state
            context.SaveChanges(); //doesn't save the entity                
            return pVideo;
        }

次に、最初にデータベースからエンティティを取得し、コンテキストにアタッチし、MapperのMapメソッドを呼び出してから、SaveChangesを呼び出す必要があると考えました。ここで私がしたこと:

    public VideoDTO UpdateVideo(VideoDTO pVideo)
    {
        Video video = context.Videos.Where(v => v.VideoId == pVideo.VideoId).FirstOrDefault();
        Mapper.Map(pVideo, video); //Error here: Can't change VideoId value on Video entity
        //context.Attach(video);
        //context.ApplyPropertyChanges("Videos", video);
        context.SaveChanges();

        return pVideo;
    }

ここで、VideoエンティティのEntityKeyプロパティによって使用されるため、プロパティVideoIdの変更が許可されないというEFの問題が発生します。素晴らしい。DTOからEFエンティティにマッピングするときに、EntityKeyプロパティが値を取得するようにマッピングを設定しました。ここで、そのマッピングルールに例外を設ける方法が必要ですが、どこから始めればよいかわかりません。このメソッドでまったく新しいマッピングルールを作成し、EntityKeyとVideoIdのプロパティを無視するように設定できると思いますが、それはかなりお粗末なようです。さらに、この時点で作成されたマッピングが固執するかどうかはわかりません。DTOがエンティティのEntityKeyに値をマップできるようにする初期設定を無効にすると、まったく異なる方法で逆効果になります。

誰かもっと良いアイデアがありますか?

4

5 に答える 5

6

AutoMapper

あなたの最初の問題は、私が知る限り、AutoMapperがDTO->エンティティのみエンティティ->DTOから移動するように設計されていないことです。これは最近変更された可能性があるので、よくわかりません。automapperの機能の詳細については、次のリンクを参照してください。 双方向マッピングの場合

PKマッピング

あなたはこう言います:「このメソッドでルールを正しくマッピングし、EntityKeyとVideoIdのプロパティを無視するように設定しますが、それはかなりずさんなようです」

だらしないとは思いません。EntityKey / PKが永続化された後は、実際には触れないでください。おそらく、何らかの方法でその静的性を体系化する必要があります。

エンティティフレームワーク

「これで、ビデオエンティティのEntityKeyプロパティによって使用されるため、プロパティVideoIdの変更が許可されないというEFの問題が発生しました。すばらしいです。」

素晴らしい?EFは、PKを更新しないように強制していません。生成されたモデルの内部には、キーのセッター内のプロパティ変更チェックがあります。解決策は、生成されたコードを変更することです。モデルのボラティリティによっては、これは実用的ではない場合がありますが、オプションです。

于 2010-01-31T02:16:03.887 に答える
3

既存のオブジェクトにマッピングしてみてください。

entity = Mapper.Map<MyDTO, NyEntity>(dto, entity); 

そして、Ignore()を所定の位置に保持します。

http://groups.google.com/group/automapper-users/browse_thread/thread/24a90f22323a27bc?fwc=1&pli=1

于 2011-12-29T15:38:58.677 に答える
1

私は同じシナリオにいます。私が得た唯一の解決策は、DTO->エンティティからのマッピングでPKフィールドを無視することです。

このようなルールは、オートマッパー構成中に次のコード行で実現できます。

 Mapper.CreateMap<MyDTO, MyEntity>().ForMember("EntityPK",r=>r.Ignore());

私の知る限り、EFを分離エンティティで機能させる唯一の方法は、SaveChangesの前にDBから取得したエンティティにDTOをマッピングすることです(例で行ったように)。

于 2010-06-05T17:33:03.540 に答える
1

.Ignore()これは、マップするすべてのエンティティにsを配置することを避けたい場合に役立つことがあります。

http://www.prosoftnearshore.com/blog/post/2012/03/14/Using-AutoMapper-to-update-Entity-Framework-properties.aspx

基本的に、スカラーではないすべてのエンティティプロパティを無視するようにAutoMapperを構成します。

AutoMapper.Mapper.CreateMap<EntityType, EntityType>()
    .ForAllMembers(o => {
         o.Condition(ctx =>
             {
                 var members = ctx.Parent.SourceType.GetMember(ctx.MemberName); // get the MemberInfo that we are mapping

                if (!members.Any())
                    return false;
                return members.First().GetCustomAttributes(typeof(EdmScalarPropertyAttribute), false).Any(); // determine if the Member has the EdmScalar attribute set
            });
    });

おそらく、プロパティがPKである場合にリセットを回避するために、いくつかの追加作業を追加できEdmScalarPropertyAttributeます(インスタンス(EntityKey == true?)のプロパティはこれを示します)。

于 2012-03-14T22:21:33.563 に答える
0

「MauricioMorales」が提供する例は、プレフィックスを使用しない場合にのみ機能することに注意してください。それらを使用する場合は、上記のコードを多かれ少なかれ次のように少し変更する必要があります。

    Mapper.CreateMap<tempOR_Order, OR_Order>()
        .ForMember(m => m.OR_ID, exp => exp.Ignore())
        .ForMember(m => m.OR_CU_ID, exp => exp.Ignore())
        .ForAllMembers(o => o.Condition(ctx =>
        {
            var members = ctx.Parent.SourceType.GetMember(ctx.MemberName); // get the MemberInfo that we are mapping

            if (!members.Any())
            {
                members = ctx.Parent.SourceType.GetMember("temp" + ctx.MemberName);
                if (!members.Any())
                    return false;
            }

            return members.First().GetCustomAttributes(typeof(EdmScalarPropertyAttribute), false).Any(); // determine if the Member has the EdmScalar attribute set
        }));

つまり、if (!members.Any())ステートメント内に追加のチェックを含める必要があります。これがないと、関数はfalseを返し、マッピングは機能しません。

于 2012-08-09T12:41:09.080 に答える