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);
    }
Marc
sumber
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.

Eugene S.
sumber
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.

Koen Luyten
sumber
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());
Jess
sumber
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);
T Gupta
sumber
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.

Serj Sagan
sumber
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?

Ony
sumber
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

Basheer AL-MOMANI
sumber
-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

Ganesh Nikam
sumber