重构Linq代码和"LINQ to Entities无法识别方法"

Tom*_*mas 5 c# linq linq-to-entities entity-framework-5

我试图重构Linq到实体查询,以防止编写重复的代码,但我无法避免"LINQ to Entities无法识别方法"异常.原因是IsUserActive方法.

我提供以下代码作为示例

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

            });
}
Run Code Online (Sandbox Code Playgroud)

是否有可能重构Linq代码以防止在我的情况下重复?

  • 我不能使用IList而不是IQueryable.
  • 我知道为什么会发生这种异常,无需解释.

Raw*_*ing 3

如果您想在很多地方使用您的方法,我认为除了将其存储为表达式然后在调用原始方法的任何地方引用该表达式之外,您别无选择:

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)
        });
}
Run Code Online (Sandbox Code Playgroud)

编辑:好的,所以这不起作用。您不能只是“调用”这样的表达式。我能想到的唯一选择是将整个Select参数转换为表达式:

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);
}
Run Code Online (Sandbox Code Playgroud)

  • 原因是LINQ无法将代码中的方法映射到SQL语句,但它可以映射表达式 (3认同)