12

次の構造のEntityFrameworkPOCOがあります。

public class Entity
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
}

ビューで使用するこのエンティティのデータ転送オブジェクトを作成しました。

public class EntityDto
{
    public int Id { get; set; }
    public string Name { get; set; }
}

これで、Global.asaxファイルに次のマッピングコードが含まれています。

Mapper.CreateMap<Entity, EntityDto>();
Mapper.CreateMap<EntityDto, Entity>(); // not sure whether I need this as well?

すべてが正常に機能しています。DTOをビューに渡してOKで、モデルEntityからの新しいインスタンスを作成できます。;EntityDtoを編集しようとすると問題が発生します。Entityこれは、オブジェクトへの変更を追跡するためにEFが作成するエンティティキーをAutoMapperが失うことによるものであることを認識していますが、いくつかのソースを読んだだけでは、決定的な解決策はないようです。エンティティを編集するために使用しているアクションは次のとおりです。

public ActionResult EditEntity(EntityDto model)
{
    var entity = context.Entities.Single(e => e.Id == model.Id);
    entity = Mapper.Map<EntityDto, Entity>(model); // this loses the Entity Key stuff
    context.SaveChanges();

    return View(model);
}

さて、これを解決するにはどうすればよいですか?できますか:

  1. どういうわけかAutoMapperに.Ignore()エンティティキーのプロパティを伝えますか?
  2. AutoMapperを入手してエンティティキーのプロパティをコピーしますか?
  3. .Attach()マップEntityして状態を変更に設定しましたか?

どんな助けでも常に感謝します。

4

3 に答える 3

21

エンティティを2番目のパラメータとしてマッピングに渡してみてください。

entity = Mapper.Map<EntityDto, Entity>(model, entity);

そうしないと、エンティティインスタンスが新しいインスタンスで上書きされ、最初の行で作成されたエンティティが失われます。

于 2012-10-31T11:12:06.140 に答える
11

マップされたエンティティを.Attach()して、状態を変更済みに設定しますか?

public ActionResult EditEntity(EntityDto model)
{
    var entity = Mapper.Map<Entity>(model);
    context.Set<Entity>().Attach(entity); // (or context.Entity.Attach(entity);)
    context.Entry<Entity>(entity).State = System.Data.EntityState.Modified;
    context.SaveChanges();
    return View(model);
}

コンテキストはどこでインスタンス化されますか?EditEntityアクションimoでこれを行う必要があります。

public ActionResult EditEntity(EntityDto model)
{
    using(var context = new MyContext())
    {
        var entity = Mapper.Map<Entity>(model);
        context.Set<Entity>().Attach(entity); // (or context.Entity.Attach(entity);)
        context.Entry<Entity>(entity).State = System.Data.EntityState.Modified;
        context.SaveChanges();
        return View(model);
    }
}
于 2012-10-31T11:26:32.903 に答える
4

DTOからエンティティへの変換にAutomapperを必要としない別の答えは、DbEntryを使用することです。

        var oldEntity = DbSet.FirstOrDefault(x => x.Id == updatedEntity.Id);
        var oldEntry = Context.Entry(oldEntity);

        oldEntry.CurrentValues.SetValues(updatedEntity);

古いエンティティを最初に取得し、変更追跡がアタッチされているため、アタッチ/状態チェックは必要ありません。また、CurrentValues.SetValuesは別のタイプを受け入れることができます。この例では、updatedEntityがDTOです。値の設定に関するドキュメントは、次のように説明されています。

指定されたオブジェクトから値を読み取ることにより、このディクショナリの値を設定します。指定されたオブジェクトは、任意のタイプにすることができます。ディクショナリ内のプロパティ名と一致し、読み取ることができる名前を持つオブジェクトのすべてのプロパティが読み取られます。他のプロパティは無視されます。これにより、たとえば、単純なデータ転送オブジェクト(DTO)からプロパティをコピーできます。

つまり、すでにオートマッパー風の方法で実行できるようです。

于 2016-09-27T20:41:17.537 に答える