2009-04-20 34 views
7

Tôi có một số truy vấn LINQ có dự phòng tôi muốn đưa ra một phần mã duy nhất. Đây là những tham gia experssions được IQueryable, và quan trọng của nó tôi không gây ra các truy vấn được đánh giá sớm hơn nó sẽ không có refactoring.refactoring LINQ Biểu thức IQueryable để loại bỏ các phần trùng lặp của các truy vấn

Đây là một câu hỏi đơn giản:

var result = 
from T in db.Transactions 
join O in db.Orders on T.OrderID equals O.OrderID 
join OD in db.OrderDetails on O.OrderID equals OD.OrderID into OrderDetails 
let FirstProductBought = OrderDetails.First().Select(OD => OD.Product.ProductName) 
select new 
{ 
    TransactionID = T.TransactionID, 
    OrderID = O.OrderID, 
    FirstProductBought = FirstProductBought 
}; 

Những gì tôi muốn đến yếu tố ra logic thứ là "đưa ra một trật tự, những gì là sản phẩm đầu tiên mua". Tôi đang sử dụng cùng một logic trong các truy vấn khác. Làm thế nào tôi có thể đưa nó vào một phương pháp chia sẻ?

Nói chung, để sử dụng lại mã và IQueryables, những gì tôi có thể làm là mã đưa IQueryable vào và tạo một IQueryable/IOrderedQueryable làm đầu ra. Với các hàm như vậy, tôi có thể xây dựng các biểu thức LINQ với mã có thể tái sử dụng mà vẫn trì hoãn truy vấn cho đến khi truy vấn được xây dựng đầy đủ. Ở đây, kể từ khi tôi chỉ có một int (orderID) Tôi không chắc chắn làm thế nào để làm cho nó hoạt động.

cảm ơn

+0

Đây là câu hỏi cấp cao tuyệt vời cho Linq'ers. Tôi hỏi cùng một điều cơ bản và không nhận được nhiều phản hồi. – Merritt

Trả lời

4

Xin lỗi trả lời câu hỏi của riêng tôi nhưng tôi đã tìm được giải pháp tốt. Tôi nghĩ rằng mặc dù điều đó phụ thuộc vào những gì bạn đang cố gắng làm, có nhiều cách khác nhau để đưa ra các biểu thức LINQ khác nhau mà không cần đánh giá IQueryable. Vì vậy, tôi hy vọng mọi người chia sẻ các giải pháp thay thế.

Giải pháp của tôi là tạo "chế độ xem" cho truy vấn được tính toán. Tôi gọi nó là một khung nhìn vì nó có rất nhiều điểm chung với một khung nhìn SQL (từ quan điểm của một máy khách LINQ). Không giống như một khung nhìn SQL, nó không thể được lập chỉ mục hoặc có các cột được duy trì. Vì vậy, bằng cách sử dụng khung nhìn này trở thành một nút cổ chai, nó sẽ là thích hợp để sử dụng một khung nhìn SQL thực tế.

static public class MyDataContextExtension 
{ 
    // The view exposes OrderSummary objects 
    public class OrderSummary 
    { 
     public OrderID { get; set; } 
     public string FirstProductListed { get; set; } 
    } 

    static public IQueryable<OrderSummary> OrderySummaryView(this MyDataContext db) 
    { 
     return (
       from O in db.Orders 
       join OD in db.OrderDetails on O.OrderID equals OD.OrderID into OrderDetails 
       let AProductBought = OrderDetails.First().Select(OD => OD.Product.ProductName) 
       let TotalCost = OrderDetails.Aggregate(0 
       select new OrderSummary() 
       { 
        OrderID = OD.OrderID, 
        FirstProductListed = AProductBought.FirstOrDefault() 
       }; 
    } 
} 

Với điều này, tôi có thể yếu tố ra phần trùng lặp của truy vấn, thay thế cho truy vấn ban đầu như sau:

var result = 
from T in db.Transactions 
join OS in db.OrderSummaryView() on T.OrderID equals OS.OrderID 
select new 
{ 
    TransactionID = T.TransactionID, 
    OrderID = T.OrderID, 
    FirstProductBought = OS.FirstProductListed 
}; 

Bạn có thể tưởng tượng các cột khác được bổ sung ... Tôi nghĩ rằng một trong mát điều đó là nếu bạn thêm cột bổ sung nhưng không sử dụng chúng trong lựa chọn cuối cùng của bạn, LINQ sẽ không thực sự truy vấn cho những thứ đó từ cơ sở dữ liệu.

1

Chúng tôi đã có cùng một vấn đề. Nó không được hỗ trợ ra khỏi hộp và nó là một vấn đề lớn cho các ứng dụng LOB. Tôi đã kết thúc viết một bài viết mã dự án về tái sử dụng biểu thức LINQ, bao gồm một tiện ích rất nhỏ gọi là LinqExpressionPrjection cho phép tái sử dụng trong các phép chiếu (bao gồm cả các loại ẩn danh).

Tìm bài viết here.

Bạn có thể nhận được lắp ráp cho việc tái sử dụng chiếu dưới dạng nuget package và nguồn là trên CodePlex.

Đã qua một thời gian kể từ khi bài đăng của bạn. Tôi hy vọng nó vẫn hữu ích cho bạn. Nếu không, có thể cho những người khác đọc chủ đề này.

+0

cảm ơn! Ý của bạn là liên kết tới http://www.codeproject.com/Articles/402594/Black-Art-LINQ-expressions-reuse? Đối với tôi, liên kết bài viết bạn đã tải cho một danh sách các bài viết của bạn. –

0

Một cách quan trọng đến yếu tố biểu thức LINQ là phải vượt qua các biểu xung quanh, ví dụ:

X GetSomeX(Expression<Func<Y, X>> map) 
{ 
    return SourceOfYs.Select(map); 
} 

Tôi có ý tưởng bằng cách nhìn vào bài viết của bài viết Barak - và mặc dù anh ấy làm nhiều hơn một chút trên đó chủ đề, tôi nghĩ rằng tôi đề cập đến mảnh này một lần nữa ở đây. Nó có vẻ là một điều đầu tiên rõ ràng để chỉ ra trực tiếp.

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