Yalnızca başlatıcılar, varlık üyeleri ve varlık gezinme özellikleri desteklenir


102

Bu istisnayı alıyorum:

Belirtilen tür üyesi 'Ücretli' LINQ to Entities'de desteklenmiyor. Yalnızca başlatıcılar, varlık üyeleri ve varlık gezinme özellikleri desteklenir.

    public ActionResult Index()
    {
        var debts = storeDB.Orders
            .Where(o => o.Paid == false)
            .OrderByDescending(o => o.DateCreated);

        return View(debts);
    }

Model sınıfım

public partial class Order
{
    public bool Paid {
        get {
            return TotalPaid >= Total;
        }
    }

    public decimal TotalPaid {
        get {
            return Payments.Sum(p => p.Amount);
        }
    }

Ödemeler, alan tutarını içeren İlgili bir tablodur, Sorgu, ödemelerle ilgili doğru bilgileri gösteren Where maddesini kaldırırsam çalışır, kodda neyin yanlış olduğuna dair herhangi bir ipucu var mı?

Önerildiği gibi çözüldü:

    public ActionResult Index()
    {
        var debts = storeDB.Orders
            .OrderByDescending(o => o.DateCreated)
            .ToList()
            .Where(o => o.Paid == false);

        return View(debts);
    }

15
Basit cevap: Linq-to-varlık sorgularında eşlenmemiş özellikleri kullanamazsınız! Yalnızca eşlenen özellikler SQL'e çevrilir.
Ladislav Mrnka

Yanıtlar:


114

Varlık, Ücretli mülkünüzü SQL'e dönüştürmeye çalışıyor ve tablo şemasının bir parçası olmadığı için yapamıyor.

Yapabileceğiniz şey, Varlığın Ücretli filtre olmadan tabloyu sorgulamasına izin vermek ve ardından Ücretli olanları filtrelemektir.

public ActionResult Index()
{
    var debts = storeDB.Orders
        //.Where(o => o.Paid == false)
        .OrderByDescending(o => o.DateCreated);

    debts = debts.Where(o => o.Paid == false);

    return View(debts);
}

Bu, elbette, tüm verileri web sunucusuna geri getirdiğiniz ve üzerindeki verileri filtrelediğiniz anlamına gelir. DB sunucusunda filtrelemek istiyorsanız, tabloda bir Hesaplanmış Sütun oluşturabilir veya bir Saklanan Yordamı kullanabilirsiniz.


25

Sadece benzer bir sorunu çözmem gerekiyordu. Yukarıdaki çözümler, kötü bir uygulama olan bellek içi işlemeyi gerektirir (geç yükleme).

Benim çözümüm, bir yüklemi döndüren bir yardımcı yazmaktı:

public static class Extensions
{
    public static Expression<Func<Order, bool>> IsPaid()
    {
        return order => order.Payments.Sum(p => p.Amount) >= order.Total;
    }
}

Linq ifadenizi şu şekilde yeniden yazabilirsiniz:

var debts = storeDB.Orders
                    .Where(Extensions.IsPaid())
                    .OrderByDescending(o => o.DateCreated);

Bu, hesaplama mantığını (KURU) yeniden kullanmak istediğinizde kullanışlıdır. Dezavantajı, mantığın etki alanı modelinizde olmamasıdır.


1
Bu yaklaşımı daha "yerleşik" hale getirmeye çalışan birkaç kitaplık vardır, bkz . Stackoverflow.com/a/27383641/470183 . Linq-to-varlık'lar, SQL'e dönüştürülebilen "Kanonik İşlevler" kullanan ifadelerle sınırlıdır. C # 6, "İfade gövdeli işlevleri" tanıttı, ancak bunlar gerçek lambdalar değil (bkz: stackoverflow.com/a/28411444/470183 ). Yine de, WIBNI data.uservoice.com/forums/…
James Close

1
Bu basit ve özlü örnek için teşekkür ederiz Expression<Func<xx,yy>>. Bunu daha önce hiç anlamadım ama şimdi apaçık görünüyor.
AlexB

17

Bu sorun, [NotMapped]DB Modelinizde ve Görünüm Modelinizde aynı ada sahip bir mülkten de gelebilir .

AutoMapper bir projeksiyon sırasında bunu DB'den seçmeye çalışır; ve NotMapped özelliği açıkça DB'de mevcut değildir.

Çözüm, IgnoreDB Modelinden Görünüm Modeline eşleme yaparken AutoMapper yapılandırmasındaki özelliktir.

  1. DB Modelinizde [NotMapped]adlı bir mülk arayın Foo.
  2. FooGörünüm Modelinizde aynı ada sahip bir mülk arayın .
  3. Durum buysa, AutoMapper yapılandırmanızı değiştirin. Ekle.ForMember(a => a.Foo, b => b.Ignore());

Dang AutoMapper Projection da beni yakaladı, yanıt için teşekkürler!
Chase Florell

15

Linq, ifadeleri SQL ifadelerine dönüştürür ve bunları veritabanında yürütür.

Artık bu dönüştürme yalnızca varlık üyeleri, başlatıcılar ve varlık gezinme özellikleri için gerçekleşir. Bu nedenle, işlev elde etmek veya özellik karşılaştırması elde etmek için, önce bunları bellek içi listelemeye dönüştürmemiz ve ardından verileri almak için işlevi uygulamamız gerekir.

Bu nedenle bütünlük içinde,

var debts = storeDB.Orders.toList()
        .Where(o => o.Paid == false)
        .OrderByDescending(o => o.DateCreated);

21
Birinden sipariş üzerine toList () yapmasını istemenin tehlikeli olduğunu, çünkü tüm listenin alınması anlamına geleceğini
öneririm

Bu benim için iyidir çünkü sorunlu özelliğim Where cümlesinde değil bir Sum Linq fonksiyonunda. Bu yüzden gereksiz veri almıyorum ve alınan veriler üzerine Listede çalışan Linq Sum işlevini yapıyorum. Teşekkür ederim! İlk başta kötü görünen bir şey, belirli durumlarda çok yardımcı olabilir!
Dov Miller

11

Diğer olası neden, IEnumerablemülkünüz için kullanmak yerineICollection

Yani bunun yerine:

public class This
{
    public long Id { get; set; }
    //...
    public virtual IEnumerable<That> Thats { get; set; }
}

Bunu yap:

public class This
{
    public long Id { get; set; }
    //...
    public virtual ICollection<That> Thats { get; set; }
}

Ve sen yakışıklı pisliksin ... 2 saat sonra kaybetmek için aptal bir şeysin.


2

Unigned int gibi EntityFramework türleri tarafından desteklenmeyen kullanıyorsanız da bu durum ortaya çıkabilir .

Bu benim böyle bir hata durumumdu.

Desteklenen türler hakkında daha fazla bilgi edinin : https://msdn.microsoft.com/en-us/library/ee382832(v=vs.100).aspx

GFoley83 tarafından açıklanan bu tür durumlar için bazı geçici çözümler vardır: Entity Framework ile unsigned int / long türleri nasıl kullanılır?


Bu bağlantı oldukça zaman kazandırdı! Çok teşekkür ederim!
Vladimir Semashkin

0

Bu sorunla karşılaştım çünkü yalnızca get without setmülkiyeti olan bir üye değişkeni vardı

bu onun auto calculatedve not storedbir sütun olarakthe table

bu nedenle onun not existiçindetable schema

böylece make sureherhangi bir üye değişkeni not auto calculatediçin havebir getterve setterözellikleri


-1

edmx ve bağlam modeliniz, db'ye yeni eklenen bazı farklı özelliklere sahiptir.

EDMX'inizi güncelleyin, uygun şekilde yenileyin Projenizi bulup yeniden çalıştırın.

Sorununuzu çözecektir.

Saygılarımızla, Ganesh Nikam

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.