2013-02-25 209 views
1

我有接受Linq Where子句的表达式的方法。有时候我会忽略Where子句,不要使用它。Linq将null传递给Where子句

我曾试图通过空的方法是这样

GetUsersView(null) 

却得到了异常。这个如何正确?

private IQueryable<UserView> GetUsersView(Expression<Func<User, bool>> expression) 
     {    
      return _userRepository.GetAll(). 
            Where(expression). 
            Select(p => new UserView 
            { 
             Id = p.Id, 
             Active = p.Orders.Any(c => c.Active && (c.TransactionType == TransactionType.Order || c.TransactionType == TransactionType.Subscription)), 
             DateStamp = p.DateStamp, 
             Email = p.Email, 
             FirstName = p.FirstName, 
             LastName = p.LastName, 
             Message = p.Message, 
             UsersManager = p.Orders.Select(o => o.Product).Any(w => w.UsersManager && w.Active) 
            }); 
     } 
+0

你为什么不检查你的表达式为空?如果它为null,则返回_userRepository.GetAll()。否则,返回你已有的东西。 – Tomtom 2013-02-25 12:07:01

+0

你尝试过'GetUsersView(true)'吗? – 2013-02-25 12:07:33

回答

2

将空值传递给方法是一个可怕的想法。通过u => true也不是很可读。改为创建两个方法 - 一个具有参数,另一个不具有参数。此外,我看到你的方法有两个职责 - 它过滤用户,并将其转换为UserViews。我认为通过谓词过滤用户应该在仓库中进行。

您还可以创建扩展方法IQueryable<UserView> ToViews(this IQueryable<User> source)

public static IQueryable<UserView> ToViews(this IQueryable<User> source) 
{ 
    return source.Select(u => new UserView 
     { 
      Id = u.Id, 
      Active = u.Orders.Any(o => o.Active && 
          (o.TransactionType == TransactionType.Order || 
          o.TransactionType == TransactionType.Subscription)), 
      DateStamp = u.DateStamp, 
      Email = u.Email, 
      FirstName = u.FirstName, 
      LastName = u.LastName, 
      Message = u.Message, 
      UsersManager = u.Orders.Select(o => o.Product) 
            .Any(p => p.UsersManager && p.Active) 
     });  
} 

在这种情况下,代码如下:

private IQueryable<UserView> GetUserViews() 
{ 
    return _userRepository.GetAll().ToViews(); 
} 

private IQueryable<UserView> GetUserViews(Expression<Func<User, bool>> predicate) 
{ 
    // move filtering to repository  
    return _userRepository.GetAll(predicate).ToViews();   
} 
+0

在Predicate参数中存储方法是一个好主意吗?或者我应该为_userRepository.GetAll(byId),_userRepository.GetAll(byEmail)等每个过滤器条件创建独立的存储库方法。 – Tomas 2013-02-25 13:37:50

+0

@Tomas我通常创建特定的存储库,它从通用存储库继承。这些特定的存储库还实现了像'IUserRepository'这样的接口,它们具有特定于用户的方法(如'FindByEmail')。另一个解决方案是使用规范和通用存储库,它接受不同的规范。 – 2013-02-25 13:45:39

1

尝试使用

GetUsersView(u=>true); 

,或者如果你不希望输入表达式的时候,你可以创建一个重载的功能,提供了一个默认的表情。

IQueryable<UserView> GetUsersView() 
{ 
    return GetUsersView(u=>true); 
} 
+0

可能值得注意的是,像entityframework这样的框架实际上将u => true转换为SQL,...在探查器中可以看到的污垢/复杂化 – 2013-07-26 12:48:28