web-dev-qa-db-ja.com

ASP.net MVC-ViewModelからEntityFrameworkエンティティにAutoMapperを使用する必要がありますか?

現在、AutoMapperを使用してEntityFrameworkエンティティをビューモデルにマップしています。

public class ProductsController : Controller
{
    private IProductRepository productRepository;

    public ProductsController(IProductRepository productRepository)
    {
         this.productRepository = productRepository;
    }

    public ActionResult Details(int id)
    {
        var product = productRepository.GetProduct(id);

        if( product == null )
            return View("NotFound");

        ProductDetailsViewModel model = Mapper.Map<Product, ProductDetailsViewModel>(product);

        return View(model);
    }
}

これはうまく機能します。私が持っている質問は、データベースを更新するためにビューモデルからエンティティに移動する必要がある場合です。これにAutoMapperを使用する必要がありますか?これは悪い/危険な慣行ですか?

AutoMapperは、複雑なタイプを単純な(フラットな)タイプにフラット化するのに適しているようですが、これまでのところ、さまざまなナビゲーションプロパティを持つエンティティのように、フラット/シンプルなタイプからより複雑なタイプに移行しようと苦労しています。

AutoMapperを使用してこれを行うのが悪い考えである場合、Createアクションのコードはどのようになりますか?

public ActionResult Create(CreateProductViewModel model)
{
    if( ModelState.IsValid )
    {
        // what do i do here to create my Product entity?
    }
}

編集アクションはどうですか?

public ActionResult Edit(int id, EditProductViewModel model)
{
    Product product = productRepository.GetProduct(id);

    // how do i convert my view model to my entity at this point???
}
21
Dismissile

私は、エンティティの更新はかなり大したことであり、自動化されたツールを使用してはならないという考え方です。プロパティを手動で設定します。

はい、それは非常に少量のコードですが、オートマッパーまたはデータベースエンティティでupdatemodelを実行すると、意図しない結果が生じる場合があります。書き込みが正しく行われていることを確認することをお勧めします。

28
John Farrell

AutoMapperは、単純なモデルから複雑なモデルを作成する方法を理解する特殊なマッピングクラスで使用します。 AutoMapperは、クラス内の1対1のマッピングとカスタムロジックを処理して、より複雑なこと(関係など)を実行するために使用されます。すべてのAutoMapper構成は、マッピングクラスの静的コンストラクターで実行されます。このコンストラクターは、マッピング構成を検証して、エラーが早期に失敗するようにします。

public class ModelMapper
{
    static ModelMapper()
    {
        Mapper.CreateMap<FooView,Foo>()
              .ForMember( f => f.Bars, opt => opt.Ignore() );

        Mapper.AssertConfigurationIsValid();
    }

    public Foo CreateFromModel( FooView model, IEnumerable<Bar> bars )
    {
         var foo = Mapper.Map<FooView,Foo>();
         foreach (var barId in model.BarIds)
         {
             foo.Bars.Add( bars.Single( b => b.Id == barId ) );
         }
         return foo;
    }
}
12
tvanfosson

また、(.EntityKey.EntityStateなどの継承されたプロパティを含む)不要なすべてのプロパティを.Ignore()する代わりに、Scalarプロパティのみをマップするように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
            });
    });

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

2

本質的に自動マッピングは悪いです、私はこれについてブログ投稿を書きました http://blog.gavryli.uk/2015/12/02/why-automapping-is-bad-for-you/

1
Ivan G.