2011-08-16 40 views
19

Đây là vấn đề: Tôi cần trả về bộ sưu tập các đối tượng có bộ sưu tập lồng nhau được lọc. Ví dụ: có một cửa hàng có đơn hàng và tôi cần trả lại bộ sưu tập với các cửa hàng bao gồm các bộ sưu tập lồng nhau có đơn hàng nhưng không có đơn đặt hàng của khách hàng được đánh dấu là đã xóa.Làm cách nào để lọc bộ sưu tập lồng ghép đối tượng Khung thực thể?

Đây là những gì tôi cố gắng làm. Nhưng vẫn không có may mắn. Mọi đề xuất đều được đề xuất :)

public List<StoreEntity> GetStores(Func<Store, bool> storeFilter, Predicate<OrderEntity> orderFileter) 
{ 
    IQueryable<StoreEntity> storeEntities = Context.Stores 
     .Include(o => o.Order) 
     .Include(cu => cu.Orders.Select(c => c.Customer)) 
     .Where(storeFilter) 
     //.Where(rcu=>rcu.Orders.Select(cu=>cu.Customer.Deleted==false)) //just test this doesn't work 
     .AsQueryable(); 

    List<StoreEntity> storeEntities = storeEntities.ToList(); 

    //storeEntities.ForEach(s => s.Orders.ToList().RemoveAll(c=>c.Customer.Deleted==true)); // doesn't work 

    foreach (StoreEntity storeEntity in storeEntities) 
    { 
     storeEntity.Orders.ToList().RemoveAll(r=>r.Customer.Deleted==true); 
    } 

    return storeEntities; 
} 

Vấn đề là bộ lọc không được áp dụng. Khách hàng đã xóa cờ được đặt là thời gian lưu trú thực sự trong bộ sưu tập.

+0

Và vấn đề là gì? Nó không biên dịch sao? Nó có ném một ngoại lệ thời gian chạy không?Liệu nó có chạy nhưng trả lại dữ liệu sai? –

+0

giải thích thêm một chút. cám ơn. –

+1

Tôi đã sử dụng gói nuget này: 'Z.EntityFramework.Plus.QueryIncludeFilter.EF6' Tài liệu ở đây: https://github.com/zzzprojects/EntityFramework-Plus/wiki/EF-Query-IncludeFilter-%7C-Entity- Framework-Include-Related-Entities-using-Where-Filter –

Trả lời

26

Bạn không thể làm điều đó trực tiếp theo cách "gọn gàng", nhưng bạn có một vài tùy chọn.
Trước hết, bạn có thể rõ ràng tải bộ sưu tập con sau khi bạn đã tìm nạp các cửa hàng. Xem phần Applying filters when explicitly loading related entities.

Nếu bạn không muốn thực hiện thêm các chuyến đi vào cơ sở dữ liệu, bạn sẽ phải xây dựng truy vấn của riêng mình và chiếu bộ sưu tập gốc và bộ sưu tập con đã lọc vào một đối tượng khác theo cách thủ công. Xem các câu hỏi sau cho ví dụ:
Linq To Entities - how to filter on child entities
LINQ Query - how sort and filter on eager fetch

Sửa

Bằng cách này, .Where(rcu=>rcu.Orders.Select(cu=>cu.Customer.Deleted==false)) nỗ lực đầu tiên của bạn không hoạt động kể từ cách này bạn đang áp dụng một bộ lọc vào bộ sưu tập cha mẹ của bạn (cửa hàng) thay vì tập hợp lồng nhau (ví dụ: tất cả các cửa hàng không có khách hàng đã xóa).
Về mặt logic, mã lọc bộ sưu tập lồng nhau phải được đặt theo phương thức Include. Hiện nay, Include chỉ hỗ trợ một tuyên bố Select, nhưng cá nhân tôi nghĩ rằng đó là thời gian cho đội EF để thực hiện một cái gì đó như:

.Include(cu => cu.Orders.Select(c => c.Customers.Where(cust => !cust.IsDeleted))); 
+0

Vâng, tôi đồng ý. (Tôi biết điều đó không hiệu quả, nhưng vẫn muốn thử nó, ai biết được rằng tính năng đó đã bị ẩn đi và tôi sẽ ngạc nhiên), và vâng, loại Bao gồm này sẽ rất tuyệt. Tôi quyết định đi với chiếu tùy chỉnh ... không thực sự thích phương pháp đó bởi vì tôi đã phải gán rất nhiều giá trị câm như (ID = r.ID, Name = r.Name ... và vv). Nhưng ít nhất nó hoạt động :) Thx –

+3

Tôi đồng ý nhóm EF nên thực hiện lọc Bao gồm. Bình chọn cho nó [ở đây] (https://entityframework.codeplex.com/workitem/47)! – Chris

+0

gì nếu tôi có một phương pháp chung được gọi là 'GetWithInclude() ' ' công IQueryable GetWithInclude (params Expression > [] includeProperties) { trở includeProperties.Aggregate >, IQueryable > (DbSet, (current, includeProperty) => current.Include (includeProperty)); } ' Tuy nhiên, tôi không có bộ sưu tập và tôi cần bộ lọc từ một phép chiếu. Nói cách khác, tôi có một tài sản cần phải bằng một cái gì đó. – Vyache

2

Vấn đề với mã bạn đang có là dòng này:

storeEntity.Orders.ToList().RemoveAll(r=>r.Customer.Deleted==true); 

storeEntity.Orders.ToList() trả lại một mớiList<OrderEntity> với nội dung của storeEntity.Orders. Từ danh sách mới này, bạn xóa tất cả khách hàng đã xóa. Tuy nhiên, danh sách này không được sử dụng ở bất cứ đâu sau đó.

Tuy nhiên, ngay cả khi nó sẽ làm những gì bạn muốn, điều này cũng sẽ loại bỏ những khách hàng đó khỏi cơ sở dữ liệu vì các đối tượng StoreEntity của bạn vẫn được kết nối với ngữ cảnh dữ liệu!

Bạn thực sự muốn sử dụng bộ lọc như bạn đã thử lần đầu tiên trong nhận xét Where. Xin vui lòng xem câu trả lời của Yakimych để được giúp đỡ về điều đó.

-5

Chủ đề cũ, nhưng tôi đã gặp phải một vấn đề tương tự. Tôi đã tìm kiếm rất nhiều và liên kết MSDN do Yakimych cung cấp cuối cùng đã gợi ý cho tôi một giải pháp: vô hiệu hóa việc tải xuống một cách rõ ràng và sau đó thực hiện truy vấn để lọc các thuộc tính điều hướng. Kết quả sau đó sẽ được "đính kèm" vào truy vấn chính, sẽ cung cấp thông tin như sau:

Context.Configuration.LazyLoadingEnabled = false; 

var filteredOrders = Context.Orders.Where(x => x.Customer.Delete == false); 

IQueryable<StoreEntity> storeEntities = Context.Stores 
.Include(o => o.Order) 
.Include(cu => cu.Orders.Select(c => c.Customer)) 
.Where(storeFilter) 
.AsQueryable(); 
+0

StoreFilter là gì? –

Các vấn đề liên quan