Sabit bir tür değeri oluşturulamıyor Bu bağlamda yalnızca ilkel türler veya numaralandırma türleri desteklenir


164

Aşağıdaki sorgu için bu hatayı alıyorum

Sabit bir tür değeri oluşturulamıyor API.Models.PersonProtocol. Bu bağlamda yalnızca ilkel türler veya numaralandırma türleri desteklenir

ppCombinedAşağıda, 2 listenin birleşmesiyle oluşturulan bir IEnumerablenesne bulunmaktadır .PersonProtocolTypePersonProtocol

Bu neden başarısız oluyor? Biz LINQ kullanamıyorum JOINfıkra inside SELECTa 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
                 })
        });


Yanıtlar:


232

Bunun nedeni çalışamaz ppCombinedbellekte nesneler topluluğudur ve bellekte olan verilerin başka bir dizi ile veritabanındaki bir veri grubunu katılamaz. Sen filtrelenmiş öğeleri ayıklamak yerine deneyebilirsiniz personProtocolait ppCombinedbellekte koleksiyonunda sonra size veritabanından diğer özellikleri aldıktan:

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
Benim için anahtar kısım .AsEnumerable () // veritabanı sorgusu burada sona eriyor, gerisi bellekte bir sorgu
Sameer Alibhai

2
@Slauma Performans hakkında endişeliysem, bunu önce tüm verileri belleğe yükleyeceği ve sonra sorgulayacağı için yapmaktan kaçınmalıyım. Bu senaryolar için ham sql yazmalı mıyım?
Arvand

@Arvand'ın harika bir noktası var gibi görünüyor. Filtreden önce çok sayıda kaydınız varsa, bu kullanılabilir bellek kaynaklarından büyük bir ısırık alabilir.
spadelives

5
@Slauma "Bu çalışamaz çünkü ppCombined bellekteki bir nesne koleksiyonudur ve veritabanındaki bir veri kümesini bellekteki başka bir veri kümesiyle birleştiremezsiniz." Böyle şeylerle ilgili belgeleri nereden bulabilirim? Gerçekten EF sınırları hakkında bilgi eksik ve bir sorgu sonuç kümesi bu şekilde kısıtlamak çalıştığınızda, bu yetersizlik kendini çok belirgin ve beni yavaşlatır.
Nomenator

1
İyi bilgi. Bu istisnayı en az sezgisel istisna mesajları listeme ekliyorum. Neden olduğunu anladıktan SONRA sadece mantıklı.
DVK

2

Kimsenin bunu aradığını bilmiyorum. Ben de aynı problemi yaşadım. Sorguda bir seçim ve sonra nerede (veya katılmak) yapmak ve select değişkenini kullanmak benim için sorunu çözdü. (sorun benim için "Yeniden Bütünleşmeler" koleksiyonundaydı)

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

Umarım bu herkese yardımcı olur.


6
zv.this.Reintegraties.FirstOrDefault().Idpotansiyel NullReferenceException

2

Benim durumumda, aşağıdakileri yaparak sorunu çözebildim:

Kodumu bundan değiştirdim:

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

Buna:

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

Bu benim için işe yaramıyor. Anonim olarak veya değişken bir adla bildirilmiş olup olmadıkları gibi p1ve p2ikisi de bellektir.
Rahat Zaman

2
Değişken türü sorun değil. Benim durumumda hata, Where yan tümcesinin içinde bir .FirstOrDefault () yapması nedeniyle oluştu.
Colin

1

OP'nin kod örneği aksini ispatlamak için yeterli bağlam sağlamadığından eklemeye değer, ancak bu hatayı aşağıdaki kodda da aldım:

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

Görünüşe göre, Int32.Equalsbu bağlamda bir Int32'yi ilkel bir int ile karşılaştırmak için kullanamıyorum ; Bunu (güvenli bir şekilde) değiştirmek zorunda kaldım:

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

EF Equalsmükemmel bir şekilde kabul eder .
Gert Arnold

0

AsEnumerable () veToList () ekleyin, böylece şöyle görünür

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

ToList().AsEnumerable()

0

Bu sorunu yaşadım ve yaptığım ve sorunu çözdüğüm , AsEnumerable()Join cümlemimden hemen önce kullandım . İşte benim sorgu:

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

Bu sorunun neden olduğunu merak ediyordum ve şimdi sanırım çünkü LINQ aracılığıyla bir sorgu yaptıktan sonra sonuç bellekte olacak ve nesnelere yüklenmeyecek, bu durumun ne olduğunu bilmiyorum ama bazılarında geçiş durumu sanırım. Sonra AsEnumerable()veya ToList(), vb. Kullandığınızda, bunları fiziksel bellek nesnelerine yerleştiriyorsunuz ve sorun çözülüyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.