Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Refactor Linq code and "LINQ to Entities does not recognize the method"

I am trying to refactor Linq to Entity query to prevent writing duplicate code but I can't avoid a "LINQ to Entities does not recognize the method" exception. The reason is IsUserActive method.

I am providing the code below as example

public static bool IsUserActive(this User user)
{
 return user.Orders.Any(c => c.Active && (c.TransactionType == TransactionType.Order || c.TransactionType == TransactionType.Subscription));
}

public IQueryable<UserView> GetView()
{
 return context.users.Select(p => new UserView
            {
                Id = p.Id,
                Active =p.IsUserActive()

            });
}

Is it possible to refactor Linq code to prevent duplication in my situation?

  • I can't use IList instead of IQueryable.
  • I know why this exception happens, no need to explain.
like image 432
Tomas Avatar asked Nov 02 '22 09:11

Tomas


1 Answers

If you want to use your method in a lot of places, I don't think you can do anything except store it as an expression and then referring to that expression wherever you were calling the original method:

public static Expression<Func<User, bool>> IsUserActive = user =>
    user.Orders.Any(c => c.Active &&
                         (c.TransactionType == TransactionType.Order ||
                          c.TransactionType == TransactionType.Subscription));

public IQueryable<UserView> GetView()
{
    return context.users.Select(p => new UserView
        {
            Id = p.Id,
            Active = IsUserActive(p)
        });
}

EDIT: OK, so this doesn't work. You can't just "call" an expression like this. The only alternative I can think of is to turn your whole Select parameter into an expression:

public static Expression<Func<User, UserView>> UserToUserView = user =>
    new UserView
        {
            Id = user.Id,
            Active =  user.Orders.Any(c => c.Active &&
                         (c.TransactionType == TransactionType.Order ||
                          c.TransactionType == TransactionType.Subscription)
        };

public IQueryable<UserView> GetView()
{
    return context.users.Select(UserToUserView);
}
like image 95
Rawling Avatar answered Nov 15 '22 05:11

Rawling