タイプの定数値を作成できませんこのコンテキストでは、プリミティブタイプまたは列挙タイプのみがサポートされています


164

以下のクエリでこのエラーが発生します

タイプの定数値を作成できませんAPI.Models.PersonProtocol。このコンテキストでは、プリミティブ型または列挙型のみがサポートされています

ppCombined以下は、2つのリストの連結によって構成されるのIEnumerableオブジェクトです。PersonProtocolTypePersonProtocol

なぜこれが失敗するのですか?私たちは、LINQを使用することはできませんJOIN内部の句をSELECTしますかJOIN

var persons = db.Favorites
    .Where(x => x.userId == userId)
    .Join(db.Person, x => x.personId, y => y.personId, (x, y) =>
        new PersonDTO
        {
            personId = y.personId,
            addressId = y.addressId,                   
            favoriteId = x.favoriteId,
            personProtocol = (ICollection<PersonProtocol>) ppCombined
                .Where(a => a.personId == x.personId)
                .Select( b => new PersonProtocol()
                 {
                     personProtocolId = b.personProtocolId,
                     activateDt = b.activateDt,
                     personId = b.personId
                 })
        });


回答:


232

ppCombinedはメモリ内のオブジェクトのコレクションであり、データベース内のデータセットをメモリ内の別のデータセットと結合できないため、これは機能しません。代わりに、データベースから他のプロパティを取得したで、メモリ内personProtocolppCombinedコレクションのフィルター処理されたアイテムを抽出することができます。

var persons = db.Favorites
    .Where(f => f.userId == userId)
    .Join(db.Person, f => f.personId, p => p.personId, (f, p) =>
        new // anonymous object
        {
            personId = p.personId,
            addressId = p.addressId,   
            favoriteId = f.favoriteId,
        })
    .AsEnumerable() // database query ends here, the rest is a query in memory
    .Select(x =>
        new PersonDTO
        {
            personId = x.personId,
            addressId = x.addressId,   
            favoriteId = x.favoriteId,
            personProtocol = ppCombined
                .Where(p => p.personId == x.personId)
                .Select(p => new PersonProtocol
                {
                    personProtocolId = p.personProtocolId,
                    activateDt = p.activateDt,
                    personId = p.personId
                })
                .ToList()
        });

10
私にとって重要な部分は.AsEnumerable()を追加することでした//データベースクエリはここで終わり、残りはメモリ内のクエリです
Sameer Alibhai

2
@Slaumaしたがって、パフォーマンスに不安がある場合は、最初にメモリ内のすべてのデータをロードしてからクエリを実行するため、これを回避する必要があります。このシナリオで生のSQLを書く必要がありますか?
Arvand

@Arvandは素晴らしい点を持っているようです。フィルターの前に多数のレコードがある場合、これにより、使用可能なメモリリソースが大量に消費される可能性があります。
spadelives 2016年

5
@Slauma「ppCombinedはメモリ内のオブジェクトのコレクションであり、データベース内のデータセットをメモリ内の別のデータセットと結合できないため、これは機能しません。」このようなことに関するドキュメントはどこにありますか?EFの制限に関する知識が本当に不足しているため、クエリの結果セットをこのように制限しようとすると、この無能さが明らかになり、速度が低下します。
ノメネーター

1
良い情報。私はこの例外を、これまでにない直感的な例外メッセージの私のリストに追加しています。それがなぜ起こっているのかを理解した後でないと意味がありません。
DVK 2018年

2

誰かがこれを検索しているかどうかわからない。私も同じ問題を抱えていました。クエリを選択してwhere(または結合)を実行し、select変数を使用すると問題が解決しました。(問題は私のためのコレクション「Reintegraties」にありました)

query.Select(zv => new
            {
                zv,
                rId = zv.this.Reintegraties.FirstOrDefault().Id
            })
            .Where(x => !db.Taken.Any(t => t.HoortBijEntiteitId == x.rId
                                             && t.HoortBijEntiteitType == EntiteitType.Reintegratie
                                             && t.Type == TaakType))
            .Select(x => x.zv);

これが誰にも役立つことを願っています。


6
zv.this.Reintegraties.FirstOrDefault().Id潜在的なNullReferenceException

2

私の場合、次のようにして問題を解決することができました。

私はコードをこれから変更しました:

var r2 = db.Instances.Where(x => x.Player1 == inputViewModel.InstanceList.FirstOrDefault().Player2 && x.Player2 == inputViewModel.InstanceList.FirstOrDefault().Player1).ToList();

これに:

var p1 = inputViewModel.InstanceList.FirstOrDefault().Player1;
var p2 = inputViewModel.InstanceList.FirstOrDefault().Player2;
var r1 = db.Instances.Where(x => x.Player1 == p1 && x.Player2 == p2).ToList();

これは私にはうまくいきません。などp1p2彼らは匿名または変数名で宣言されているかどうかメモリの両方です。
Rahat Zaman

2
変数の型は問題ではありません。私の場合、エラーはWhere句内で.FirstOrDefault()を実行していたために発生しました。
コリン

2

OPのコードサンプルでは、​​それ以外のことを証明するための十分なコンテキストが提供されていないため、追加する価値がありますが、次のコードでもこのエラーを受け取りました。

public RetailSale GetByRefersToRetailSaleId(Int32 refersToRetailSaleId)
{
    return GetQueryable()
        .FirstOrDefault(x => x.RefersToRetailSaleId.Equals(refersToRetailSaleId));
}

どうやら、Int32.EqualsこのコンテキストではInt32とプリミティブintを比較するために使用できません。これに(安全に)変更する必要がありました。

public RetailSale GetByRefersToRetailSaleId(Int32 refersToRetailSaleId)
{
    return GetQueryable()
      .FirstOrDefault(x => x.RefersToRetailSaleId == refersToRetailSaleId);
}

EFはEquals完全に受け入れます。
Gert Arnold

0

AsEnumerable()とToList()を追加するだけなので、次のようになります

db.Favorites
    .Where(x => x.userId == userId)
    .Join(db.Person, x => x.personId, y => y.personId, (x, y).ToList().AsEnumerable()

ToList().AsEnumerable()

0

この問題があり、Join句の直前で使用したことが問題を解決しましAsEnumerable()。これが私のクエリです:

List<AccountViewModel> selectedAccounts;

 using (ctx = SmallContext.GetInstance()) {
                var data = ctx.Transactions.
                    Include(x => x.Source).
                    Include(x => x.Relation).
                    AsEnumerable().
                    Join(selectedAccounts, x => x.Source.Id, y => y.Id, (x, y) => x).
                    GroupBy(x => new { Id = x.Relation.Id, Name = x.Relation.Name }).
                    ToList();
            }

この問題は、なぜ起こるか私は思っていた、そして今、私はあなたが経由で問い合わせを行った後だからだと思うLINQ、結果はメモリ内にあり、オブジェクトにロードされませんが、私は知らないという状態が何であるかが、彼らはいくつかの中にあります過渡期の状態だと思います。次に、AsEnumerable()or ToList()、などを使用すると、それらが物理メモリオブジェクトに配置され、問題が解決します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.