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プロジェクトに関する問題も公開しました。
EntityFrameworkCore: https://github.com/aspnet/EntityFrameworkCore/issues/110
AutoMapper: https://github.com/AutoMapper/AutoMapper/issues/2537
これはEFCoreのバグであり、EF Core 2.1で修正されています https://github.com/aspnet/EntityFrameworkCore/issues/110
詳細がないと何が問題になっているのかを正確に特定することは困難ですが、マッピングが正しいことを確認してください。マッピングプロファイルを使用する場合
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();