web-dev-qa-db-ja.com

AutoMapperProjectToおよびUnionsでEFCoreを正しく使用するにはどうすればよいですか?

私のセットアップ

  • ASP.NET Core 2.0
  • EntityFrameworkCore 2.0.1
  • AutoMapper 6.2.2

問題

PersonDetailという名前のDTOとPersonという名前のエンティティを持つプロジェクトがあります。私が電話するとき

db.People.Where(p => p.FirstName == "Joe").Union(db.People.Where(p => Age > 30)).ProjectTo<PersonDetail>(mapperConfig).ToList(); 

PersonDetail DTOが取得されず、Entity Framework(Core)が次のメッセージで例外をスローします。

ArgumentException:入力シーケンスには「Test.Module.Entities.Person」タイプのアイテムが必要ですが、「Test.Module.Dtos.PersonDetail」タイプのアイテムがあります。


問題のない例

コードを実行すると:

 db.People.Where(p => p.FirstName == "Joe").Union(db.People.Where(p => Age > 30)).ToList(); 

例外なくPersonエンティティを取得します。


実行計画

これが(組合との)作業計画です:

{value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1 [Test.Module.Entities.Person])。Where(entity =>((entity!= null)And((63ed0ebd-2c02-4496-ac8d-b836cbf13259 = = entity.CreatedBy)または(393a6bb0-b437-4664-beb0-6800f509451b == entity.CreatedBy))))。Union(value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1 [Test.Module.Entities.Person] ))}

これは同じ計画ですが、オートマッパープロジェクションもあります。

{value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1 [Test.Module.Entities.Person])。Where(entity =>((entity!= null)And((63ed0ebd-2c02-4496-ac8d-b836cbf13259 = = entity.CreatedBy)または(393a6bb0-b437-4664-beb0-6800f509451b == entity.CreatedBy))))。Union(value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1 [Test.Module.Entities.Person] ))。Select(dto => new PersonDetail(){FirstName = dto.FirstName、LastName = dto.LastName、Deleted = dto.Deleted、Age = dto.Age、CreatedUtc = dto.CreatedUtc、CreatedBy = dto.CreatedBy、Id = dto.Id、RecordVersion = dto.RecordVersion、DisplayLabel =((dto.FirstName + "")+ dto.LastName)})}


注意:

この問題を最小の形式に減らすために、ToListを呼び出すだけです。この例ではProjectToを使用する必要がないように思われることを理解しています。私の実際のコードでは、ODataを使用しており、最終結果は、クエリ可能なオブジェクトとしてDTOを使用した投影クエリである必要があります。また、この連合は、連合の問題を単純化するためだけに、実際には良い組合の例ではないことも理解しています。

Iaは、それぞれのGitHubプロジェクトに関する問題も公開しました。

EntityFrameworkCorehttps://github.com/aspnet/EntityFrameworkCore/issues/110

AutoMapperhttps://github.com/AutoMapper/AutoMapper/issues/2537

5
Phobis

これはEFCoreのバグであり、EF Core 2.1で修正されています https://github.com/aspnet/EntityFrameworkCore/issues/110

1
Phobis

詳細がないと何が問題になっているのかを正確に特定することは困難ですが、マッピングが正しいことを確認してください。マッピングプロファイルを使用する場合

public class MappingProfile : Profile
{
    public MappingProfile()
    {
        CreateMap<Person, PersonDetail>();
    }
}

そして、EFコンテキストにセットがあると仮定します。

public virtual DbSet<Person> People { get; set; }

次に、以下のようにコンテキストとプロジェクトをクエリできるはずです。

var details = _context.People
    .Where(p => p.LastName == 'Smith')
    .OrderBy(p => p.FirstName)
    .ProjectTo<PersonDetail>
    .ToList();

EFはエンティティではない結果タイプを追跡しないため、AsNoTrackingは必要ありません。 追跡と予測 のドキュメントを参照してください。

---更新---

EF Coreはメモリ内で評価しますが、以下は機能するはずです。

var firstNameQuery = db.People
    .Where(p => p.FirstName == "Joe")
    .ProjectTo<PersonDetail>(mapperConfig);
var ageQuery = db.People
    .Where(p => p.FirstName == "Joe")
    .ProjectTo<PersonDetail>(mapperConfig);
var results = firstNameQuery.Union(ageQuery).ToList();
1
ChrisR