2010-11-03 43 views
7

Tôi có một phương thức gọi là GetAge (DateTime birthDay). Tôi muốn sử dụng phương pháp này trong Truy vấn LINQ bằng cách chuyển sinh nhật và dựa trên giá trị tuổi được trả về cần phải hoàn thiện một số logic.Phương thức gọi theo lớp bên trong Truy vấn LINQ

Tôi muốn dưới đây truy vấn dưới dạng LINQ -

from customer in contetx.Customer where 
    if GetAge(customer.BirthDate) > 20 and customer.accountType="Savings" 
    or 
    if(GetAge(customer.BirthDate) > 40 and customer.AccountType="Current" 

giúp đỡ trước mắt sẽ được đánh giá cao.

+2

Đây có phải là LINQ to SQL không? – Ani

+0

Đây là LINQ đối với thực thể. Tôi đang sử dụng khung Entity. –

Trả lời

6
context.Customer 
     .AsEnumerable() // because the method has no translation to SQL 
     .Where(customer => (GetAge(customer.BirthDate) > 20 && customer.AccountType == "Savings") 
         || (GetAge(customer.BirthDate) > 40 && customer.AccountType == "Current")); 

Các .AsEnumerable là cần thiết nếu bạn đang cố gắng để truy vấn một cơ sở dữ liệu SQL như là phương pháp getAge trong mã của bạn sẽ không có dịch để SQL. Trong trường hợp đó, lệnh gọi tới số .AsEnumerable truy xuất kết quả truy vấn đến thời điểm đó và sau đó bạn làm việc với các đối tượng địa phương mà phương pháp của bạn có thể hoạt động.

Nếu bạn không muốn truy xuất tất cả kết quả tại thời điểm đó vì số lượng bản ghi lớn, bạn luôn có thể sao chép logic từ phương thức bạn muốn gọi trong truy vấn của mình (tôi đoán logic ở đây):

context.Customer.Select(c => new { Customer = c, Age = (DateTime.Today.Year - c.BirthDate.Year) } 
       .Where(c => (c.Age > 20 && c.Customer.AccountType == "Savings") 
         || (c.Age > 40 && c.Customer.AccountType == "Current")) 
       .Select(c => c.Customer); 

Bởi vì các thao tác đều có sẵn trong SQL, thao tác này sẽ hoạt động.

Nếu phương pháp bạn đang cố gắng gọi đặc biệt phức tạp, bạn luôn có thể di chuyển nó sang phương thức tiện ích có số IQueryable và trả lại IQueryable. Nội dung của phương thức vẫn sẽ cần phải có một bản dịch hợp lệ cho SQL nhưng nó sẽ giúp ẩn logic phức tạp hơn.

Ví dụ truy vấn trên có thể được thực hiện để trông như thế này:

context.Customers.WhoAreValidByAge(); 

đâu WhoAreValidByAge được định nghĩa là:

public static IQueryable<Customer> WhoAreValidByAge(this IQueryable<Customer> customers) 
{ 
    cusomters.Select(c => new { Customer = c, Age = (DateTime.Today.Year - c.BirthDate.Year) } 
      .Where(c => (c.Age > 20 && c.Customer.AccountType == "Savings") 
         || (c.Age > 40 && c.Customer.AccountType == "Current")) 
      .Select(c => c.Customer) 
} 

Nếu logic chứa trong phương pháp của bạn không dịch để SQL vì một số lý do mặc dù bạn không có lựa chọn nào khác ngoài việc chuyển đổi các kết quả thành LinqToObjects. Trong trường hợp đó, tôi khuyên bạn nên lọc kết quả càng nhiều càng tốt trong SQL trước khi gọi AsEnumerable.

+2

Tôi không nghĩ rằng nó cần thiết để gọi 'AsEnumerable() '. –

+0

Anh ấy đang điều hành trực tiếp trên ngữ cảnh bằng cách sử dụng một phương pháp, theo như tôi biết được thông tin trong câu hỏi, không có bản dịch trực tiếp sang Sql. Nếu anh ta không chuyển đổi thành LinqToObjects (sử dụng .AsEnumable() hoặc .ToList()) thì cố gắng truy cập thông tin được truy vấn trả về sẽ ném một NotSupportedException với thông báo 'GetAge' không có bản dịch được hỗ trợ cho SQL ... –

+0

right Calling AsEnumerable có thể không cần thiết lấy tất cả dữ liệu tại thời điểm đó trong truy vấn từ cơ sở dữ liệu. –

11
var customers = from customer in contetx.Customer 
       let age = GetAge(customer.BirthDate) 
       where (age > 20 && customer.accountType == "Savings") || 
         (age > 40 && customer.accountType == "Current") 
       select customer; 
+0

+1 | Nice, không biết về từ khóa 'let' –

+0

Có, nó tránh tính toán lại độ tuổi hai lần. –

+0

heyy này là tuyệt vời ... Tôi không biết 'let' từ khóa .. Darin ur champ ... Cảm ơn rất nhiều tiết kiệm rất nhiều thời gian của tôi ... –

0

Bạn có thể làm điều này:

var query = from customer in contetx.Customer 
    where (GetAge(customer.BirthDate) > 20 && customer.AccountType == "Saving") || 
      (GetAge(customer.BirthDate) > 40 && customer.AccountType == "Current") 
    select customer; 

Bạn có thể nhận được xung quanh gọi GetAge hai lần bằng cách sử dụng các từ khóa let như Darin đã làm.

var query from customer in // ... 
    let age = GetAge(customer.BirthDate) 
    where // ... 
select customer; 
+0

là điều này có thể có hai các mệnh đề như thế này? –

+0

không, không phải. truy vấn sẽ hoạt động nếu bạn xóa câu trả lời thứ hai 'where' –

+0

'không phải - cập nhật câu trả lời của tôi –

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