Hanya penginisialisasi, anggota entitas, dan properti navigasi entitas yang didukung


102

Saya mendapatkan pengecualian ini:

Anggota jenis tertentu 'Berbayar' tidak didukung di LINQ ke Entitas. Hanya penginisialisasi, anggota entitas, dan properti navigasi entitas yang didukung.

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

        return View(debts);
    }

Kelas Model saya

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

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

Pembayaran adalah tabel terkait yang berisi jumlah bidang, Kueri berfungsi jika saya menghapus klausa Di mana yang menampilkan informasi yang benar tentang pembayaran, ada petunjuk apa yang salah dengan kode tersebut?

Dipecahkan seperti jawaban yang disarankan dengan:

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

        return View(debts);
    }

15
Jawaban sederhana: Anda tidak dapat menggunakan properti yang tidak dipetakan di kueri linq-ke-entitas! Hanya properti yang dipetakan yang diterjemahkan ke SQL.
Ladislav Mrnka

Jawaban:


114

Entitas mencoba mengonversi properti Berbayar Anda ke SQL dan tidak bisa karena itu bukan bagian dari skema tabel.

Yang dapat Anda lakukan adalah membiarkan Entitas melakukan kueri tabel tanpa filter Berbayar, lalu memfilter yang tidak Berbayar.

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

Itu, tentu saja, berarti Anda membawa semua data kembali ke server web dan memfilter data di dalamnya. Jika Anda ingin memfilter pada server DB, Anda dapat membuat Kolom Terhitung pada tabel atau menggunakan Prosedur Tersimpan.


25

Hanya harus menyelesaikan masalah serupa. Solusi di atas membutuhkan pemrosesan dalam memori, yang merupakan praktik yang buruk (pemuatan lambat).

Solusi saya adalah menulis pembantu yang mengembalikan predikat:

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

Anda dapat menulis ulang pernyataan linq Anda sebagai:

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

Ini berguna saat Anda ingin menggunakan kembali logika kalkulasi (KERING). Kelemahannya adalah logikanya tidak ada dalam model domain Anda.


1
Ada sejumlah pustaka yang mencoba membuat pendekatan ini lebih "bawaan" lihat: stackoverflow.com/a/27383641/470183 . Linq-ke-entitas terbatas pada ekspresi yang menggunakan "Fungsi Kanonis" - yang dapat diubah menjadi SQL. C # 6 memperkenalkan "Fungsi bertubuh ekspresi" tetapi ini bukan lambda sejati (lihat: stackoverflow.com/a/28411444/470183 ). Masih akan lebih baik untuk memiliki ini dalam kerangka kerja maka data WIBNI.uservoice.com/forums/…
James Tutup

1
Terima kasih untuk contoh yang sederhana dan ringkas ini Expression<Func<xx,yy>>. Saya pernah memahaminya sebelumnya, tetapi sepertinya sudah jelas sekarang.
AlexB

17

Masalah ini juga dapat berasal dari [NotMapped]properti yang memiliki nama yang sama di Model DB dan Model Tampilan Anda.

AutoMapper mencoba untuk memilihnya dari DB selama proyeksi; dan properti NotMapped jelas tidak ada di DB.

Solusinya adalah untuk Ignoreproperti di konfigurasi AutoMapper saat memetakan dari Model DB ke Model Tampilan.

  1. Cari [NotMapped]properti dengan nama Foodi Model DB Anda.
  2. Cari properti dengan nama yang sama Foo,, di Model Tampilan Anda.
  3. Jika demikian, ubah konfigurasi AutoMapper Anda. Menambahkan.ForMember(a => a.Foo, b => b.Ignore());

Proyeksi Dang AutoMapper menangkap saya juga, terima kasih atas jawabannya!
Mengejar Florell

15

Linq mengubah pernyataan menjadi pernyataan SQL dan mengeksekusinya ke dalam database.

Sekarang, konversi ini hanya terjadi untuk anggota entitas, penginisialisasi, dan properti navigasi entitas. Jadi untuk mencapai fungsi atau mendapatkan perbandingan properti, pertama-tama kita perlu mengubahnya menjadi listing dalam memori dan kemudian menerapkan fungsi untuk mengambil data.

Oleh karena itu secara totalitas,

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

21
Saya akan menyarankan bahwa meminta seseorang untuk membuat toList () pada pesanan berbahaya karena itu berarti mengambil seluruh daftar
elgrego

Ini bagus untuk saya karena properti bermasalah saya ada di fungsi Sum Linq bukan di klausa Where. Jadi saya tidak mendapatkan data yang tidak perlu dan pada data yang diambil saya melakukan fungsi Linq Sum yang bekerja pada Daftar. Terima kasih! Apa yang terlihat buruk pada awalnya bisa sangat membantu dalam situasi tertentu!
Dov Miller

11

Kemungkinan alasan lainnya adalah karena Anda menggunakan IEnumerableuntuk properti Anda, bukanICollection

Jadi, alih-alih:

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

Melakukan hal ini:

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

Dan kau keren ... bodoh kehilangan 2 jam lebih.


2

Situasi ini juga dapat terjadi jika Anda menggunakan jenis EntityFramework yang tidak didukung , seperti unsigned int.

Ini adalah kasus kesalahan saya.

Lihat informasi lebih lanjut tentang jenis yang didukung: https://msdn.microsoft.com/en-us/library/ee382832(v=vs.100).aspx

Ada beberapa solusi untuk situasi seperti itu, dijelaskan oleh GFoley83: Bagaimana cara menggunakan tipe unsigned int / long dengan Entity Framework?


Tautan ini menghemat banyak waktu! Terima kasih banyak!
Vladimir Semashkin

0

Saya menghadapi masalah ini karena memiliki variabel anggota dengan hanya get without setproperti

itu artinya itu auto calculateddan not storedsebagai kolom dithe table

oleh karena itu not existditable schema

sehingga make surebahwa setiap variabel anggota not auto calculateduntuk havesebuah getterdan settersifat


-1

edmx dan model konteks Anda memiliki beberapa properti berbeda yang baru ditambahkan ke db.

Perbarui EDMX Anda, segarkan dengan benar Bulid proyek Anda dan jalankan lagi.

Ini akan menyelesaikan masalah Anda.

Salam, Ganesh Nikam

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.