Tidak dapat membuat nilai tipe konstan. Hanya tipe primitif atau tipe enumerasi yang didukung dalam konteks ini

164

Saya mendapatkan kesalahan ini untuk kueri di bawah ini

Tidak dapat membuat nilai tipe konstan API.Models.PersonProtocol. Hanya tipe primitif atau tipe enumerasi yang didukung dalam konteks ini

ppCombineddi bawah ini adalah IEnumerableobjek PersonProtocolType, yang dibangun oleh concat dari 2 PersonProtocoldaftar.

Mengapa ini gagal? Kita tidak bisa menggunakan LINQ JOINklausul dalam SELECTdari 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
                 })
        });
pengguna2515186
sumber

Jawaban:

232

Ini tidak dapat berfungsi karena ppCombinedkumpulan objek di memori dan Anda tidak dapat bergabung dengan satu set data dalam database dengan set data lain yang ada di memori. Anda bisa mencoba mengekstrak item yang difilter personProtocoldari ppCombinedkoleksi dalam memori setelah Anda mengambil properti lain dari database:

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()
        });
Slauma
sumber
10
Bagian kunci bagi saya adalah menambahkan .AsEnumerable () // query database berakhir di sini, sisanya adalah query dalam memori
Sameer Alibhai
2
@ Sabuma Jadi jika saya khawatir tentang kinerja saya harus menghindari melakukan ini karena akan memuat semua data dalam memori terlebih dahulu dan kemudian query. Haruskah saya menulis sql mentah untuk skenario ini?
Arvand
Sepertinya @Arvand memiliki poin bagus. Jika Anda memiliki sejumlah besar rekaman sebelum filter, ini bisa menghabiskan banyak sumber daya memori yang tersedia.
benteng
5
@Slauma "Ini tidak bisa berfungsi karena ppCombined adalah kumpulan objek dalam memori dan Anda tidak bisa menggabungkan satu set data dalam database dengan set data lain yang ada dalam memori." Di mana saya dapat menemukan dokumentasi tentang hal-hal seperti ini? Saya benar-benar tidak memiliki pengetahuan tentang batasan EF, dan ketika saya mencoba membatasi hasil kueri yang ditetapkan seperti ini, ketidakmampuan ini membuat dirinya sangat jelas dan memperlambat saya.
Nomenator
1
Informasi yang baik Saya menambahkan pengecualian ini ke daftar pesan pengecualian paling tidak intuitif saya. Itu hanya masuk akal SETELAH Anda mengerti mengapa itu terjadi.
DVK
2

Tidak tahu apakah ada yang mencari ini. Saya memiliki masalah yang sama. Pilih pada kueri dan kemudian melakukan di mana (atau bergabung) dan menggunakan variabel pilih memecahkan masalah bagi saya. (Masalahnya ada di koleksi "Reintegraties" untuk saya)

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);

Semoga ini bisa membantu siapa saja.

Roelant
sumber
6
zv.this.Reintegraties.FirstOrDefault().IdNullReferenceException potensial
2

Dalam kasus saya, saya dapat menyelesaikan masalah dengan melakukan hal berikut:

Saya mengubah kode saya dari ini:

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

Untuk ini:

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();
Colin
sumber
Ini tidak bekerja untuk saya. As p1dan p2keduanya dalam memori apakah mereka dinyatakan secara anonim atau dengan nama variabel.
Rahat Zaman
2
Jenis variabel bukan masalahnya. Dalam kasus saya kesalahan ini disebabkan karena sedang melakukan .FirstOrDefault () di dalam klausa Di mana.
Colin
2

Perlu ditambahkan, karena sampel kode OP tidak memberikan konteks yang cukup untuk membuktikan sebaliknya, tetapi saya menerima kesalahan ini juga pada kode berikut:

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

Rupanya, saya tidak bisa menggunakan Int32.Equalsdalam konteks ini untuk membandingkan Int32 dengan int primitif; Saya harus (dengan aman) mengubah ini:

public RetailSale GetByRefersToRetailSaleId(Int32 refersToRetailSaleId)
{
    return GetQueryable()
      .FirstOrDefault(x => x.RefersToRetailSaleId == refersToRetailSaleId);
}
James Perih
sumber
EF menerima dengan Equalssangat baik.
Gert Arnold
0

Cukup tambahkan AsEnumerable () danToList (), sehingga terlihat seperti ini

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

ToList().AsEnumerable()
Saleh khaled
sumber
0

Saya memiliki masalah ini dan apa yang saya lakukan dan memecahkan masalah adalah bahwa saya menggunakan AsEnumerable()sebelum klausa Gabung saya. ini pertanyaan saya:

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();
            }

Saya bertanya-tanya mengapa masalah ini terjadi, dan sekarang saya pikir itu karena setelah Anda membuat kueri melalui LINQ , hasilnya akan ada di memori dan tidak dimuat ke objek, saya tidak tahu apa itu keadaan tetapi mereka berada di dalam beberapa keadaan transisi saya pikir. Kemudian ketika Anda menggunakan AsEnumerable()atau ToList(), dll, Anda menempatkan mereka ke dalam objek memori fisik dan masalah terselesaikan.

ebrahim.mr
sumber