Chỉ hỗ trợ trình khởi tạo, thành viên thực thể và thuộc tính điều hướng thực thể


102

Tôi nhận được ngoại lệ này:

Thành viên loại được chỉ định 'Trả phí' không được hỗ trợ trong LINQ cho các thực thể. Chỉ hỗ trợ trình khởi tạo, thành viên thực thể và thuộc tính điều hướng thực thể.

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

        return View(debts);
    }

Lớp người mẫu của tôi

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

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

Thanh toán là một bảng Liên quan chứa số tiền trường, Truy vấn sẽ hoạt động nếu tôi loại bỏ mệnh đề Ở đâu hiển thị thông tin chính xác về các khoản thanh toán, bất kỳ manh mối nào có lỗi với mã?

Giải quyết như câu trả lời được đề xuất với:

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

        return View(debts);
    }

15
Câu trả lời đơn giản: Bạn không thể sử dụng các thuộc tính không được ánh xạ trong các truy vấn linq-to-entity! Chỉ các thuộc tính được ánh xạ mới được dịch sang SQL.
Ladislav Mrnka

Câu trả lời:


114

Thực thể đang cố gắng chuyển đổi thuộc tính Paid của bạn sang SQL và không thể vì nó không phải là một phần của lược đồ bảng.

Những gì bạn có thể làm là để Đối tượng truy vấn bảng không có bộ lọc Trả phí và sau đó lọc ra những bảng không phải trả phí.

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

Tất nhiên, điều đó có nghĩa là bạn đưa tất cả dữ liệu trở lại máy chủ web và lọc dữ liệu trên đó. Nếu bạn muốn lọc trên máy chủ DB, bạn có thể tạo một Cột được Tính toán trên bảng hoặc sử dụng Thủ tục Đã Lưu trữ.


25

Chỉ cần phải giải quyết một vấn đề tương tự. Các giải pháp trên yêu cầu xử lý trong bộ nhớ, đây là một thực tế không tốt (tải chậm).

Giải pháp của tôi là viết một trình trợ giúp trả về một vị từ:

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

Bạn có thể viết lại câu lệnh linq của mình dưới dạng:

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

Điều này rất hữu ích khi bạn muốn sử dụng lại logic tính toán (DRY). Nhược điểm là logic không có trong mô hình miền của bạn.


1
Có một số thư viện cố gắng làm cho cách tiếp cận này được "tích hợp sẵn" hơn, hãy xem: stackoverflow.com/a/27383641/470183 . Linq-to-entity được giới hạn trong các biểu thức sử dụng "Canonical Functions" - có thể được chuyển thành SQL. C # 6 đã giới thiệu "Các hàm thân biểu thức" nhưng đây không phải là lambdas thực sự (xem: stackoverflow.com/a/28411444/470183 ). Tuy nhiên, sẽ rất tốt nếu có điều này trong khuôn khổ do đó dữ liệu WIBNI.uservoice.com/forums/…
James Close

1
Cảm ơn bạn vì ví dụ đơn giản và ngắn gọn này Expression<Func<xx,yy>>. Tôi đã từng hiểu nó trước đây, nhưng bây giờ nó có vẻ hiển nhiên.
AlexB

17

Vấn đề này cũng có thể đến từ một [NotMapped] tính có cùng tên trong Mô hình DB và Mô hình dạng xem của bạn.

AutoMapper cố gắng chọn nó từ DB trong một phép chiếu; và thuộc tính NotMapped rõ ràng không tồn tại trong DB.

Giải pháp là đối với Ignorethuộc tính trong cấu hình AutoMapper khi ánh xạ từ Mô hình DB sang Mô hình dạng xem.

  1. Tìm [NotMapped]tài sản có tênFoo trong Mô hình DB của bạn.
  2. Tìm tài sản có cùng tên, Foo , trong Mô hình dạng xem của bạn.
  3. Nếu đúng như vậy, hãy thay đổi cấu hình AutoMapper của bạn. Thêm vào.ForMember(a => a.Foo, b => b.Ignore());

Dang AutoMapper Projection cũng bắt gặp tôi, cảm ơn vì câu trả lời!
Chase Florell

15

Linq chuyển đổi các câu lệnh thành câu lệnh SQL và thực thi chúng vào cơ sở dữ liệu.

Bây giờ, chuyển đổi này chỉ xảy ra cho các thành viên thực thể, trình khởi tạo và thuộc tính điều hướng thực thể. Vì vậy, để đạt được chức năng hoặc nhận được so sánh thuộc tính, trước tiên chúng ta cần chuyển đổi chúng thành danh sách trong bộ nhớ và sau đó áp dụng hàm để truy xuất dữ liệu.

Do đó về tổng thể,

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

21
Tôi sẽ đề nghị rằng yêu cầu ai đó làm một ToList () trên đơn đặt hàng rất nguy hiểm vì nó có nghĩa là lấy toàn bộ danh sách
elgrego

Điều này tốt cho tôi vì thuộc tính có vấn đề của tôi nằm trong một hàm Sum Linq không nằm trong mệnh đề Where. Vì vậy, tôi không nhận được dữ liệu không cần thiết và trên dữ liệu được lấy lại, tôi đang thực hiện hàm Linq Sum đang hoạt động trên Danh sách. Cảm ơn bạn! Những gì thoạt nhìn có vẻ không tốt có thể rất hữu ích trong một số tình huống nhất định!
Dov Miller

11

Lý do có khả năng khác là vì bạn đang sử dụng IEnumerablecho tài sản của mình, thay vìICollection

Vì vậy, thay vì:

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

Làm cái này:

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

Và bạn thật ngu ngốc ... thật ngu ngốc khi mất 2 giờ đồng hồ.


2

Tình huống này cũng có thể xảy ra nếu bạn đang sử dụng các loại EntityFramework không được hỗ trợ , chẳng hạn như int unsigned.

Đây là trường hợp của tôi về lỗi như vậy.

Kiểm tra thêm thông tin về các loại được hỗ trợ: https://msdn.microsoft.com/en-us/library/ee382832(v=vs.100).aspx

GFoley83 giải thích một số cách giải quyết cho những trường hợp như vậy: Làm thế nào để sử dụng kiểu int / long không dấu với Entity Framework?


Liên kết này đã tiết kiệm được khá nhiều thời gian! Cảm ơn bạn rất nhiều!
Vladimir Semashkin

0

Tôi gặp phải vấn đề này vì có một biến thành viên chỉ có thuộc get without settính

điều đó có nghĩa là nó auto calculatednot storednhư một cột trongthe table

do đó nó not existtrongtable schema

để make surebất kỳ biến thành viên nào not auto calculatedđối với havea gettersettercác thuộc tính


-1

edmx và mô hình ngữ cảnh của bạn có một số thuộc tính khác nhau mới được thêm vào db.

Cập nhật EDMX của bạn làm mới nó đúng cách Bulid dự án của bạn và chạy lại.

Nó sẽ giải quyết vấn đề của bạn.

Trân trọng, Ganesh Nikam

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.