开发者

Call class method inside the Linq Query

I have a method called GetAge(DateTime birthDay). I want to use this method in the Linq Query by passing the birthday and based on the returned age value need to perfrom some logic.

I want below query in LINQ format -

  from customer in contetx.Customer where 
  if GetAge(customer.Bi开发者_StackOverflow中文版rthDate) > 20 and customer.accountType="Savings"
  or
  if(GetAge(customer.BirthDate) > 40 and customer.AccountType="Current"

Immediate help would be highly appreciated.


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

The .AsEnumerable is required if you're attempting to query an SQL database as the GetAge method in your code will have no translation to SQL. In that case the call to .AsEnumerable retrieves the results of the query up to that point and you're then working with local objects on which your method can operate.

If you don't want to retrieve all the results at that point because the number of records is large you could always replicate the logic from the method you want to call in your query (I'm guessing at the logic here):

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

Because the operations are all available in SQL this will work.

If the method you're trying to call is particularly complex you can always move it to an extension method that takes an IQueryable and returns an IQueryable. The contents of the method will still need to have a valid translation to SQL but it will help hide more complicated logic.

For example the above query could be made to look like this:

context.Customers.WhoAreValidByAge();

Where WhoAreValidByAge is defined as:

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

If the logic contained in your method doesn't translate to SQL for some reason though you have no choice but to convert the results set to LinqToObjects. In that case I'd suggest filtering the results as much as possible in SQL before calling AsEnumerable.


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;


You could do this:

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

You could get around calling GetAge twice by using the let keyword as Darin did.

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜