2011-05-25 68 views
0

我现在有这样对我仓库里的方法:如何构造部分动态的LINQ语句?

public int GetMessageCountBy_Username(string username, bool sent) 
    { 
     var query = _dataContext.Messages.AsQueryable(); 

     if (sent) 
      query = query.Where(x => x.Sender.ToLower() == username.ToLower()); 
     else 
      query = query.Where(x => x.Recipient.ToLower() == username.ToLower()); 

     return query.Count(); 
    } 

目前,它建立了基于该sent布尔两个查询之一。这是做到这一点的最佳方式,还是有一种方法可以在查询本身内执行此操作吗?我想检查x.Sender是否等于username如果sent等于true。但是我想检查x.Recipient是否等于username如果sent等于false。

然后我想要这个LINQ表达式转换为实体框架中的SQL,我相信它正在做。

我只是想避免重复尽可能多的代码。

回答

2

你可以做这样的事情:

public int GetMessageCountBy_Username(string username, bool sent) 
{ 
    Func<Message, string> userSelector = m => sent ? m.Sender : m.Recipient; 
    var query = 
    _dataContext.Messages.AsQueryable() 
    .Where(x => userSelector(x).ToLower() == username.ToLower()); 
    return query.Count(); 
} 

因此,正确的用户(发件人或收件人)的选择LINQ部分之前完成,从重复两次拯救你。

+0

Bravo!这更有意义。谢谢。 – Chev 2011-05-25 13:45:27

+0

虽然我修改了一些功能。 lambda声明必须先于inline IF语句。 – Chev 2011-05-25 17:03:02

+0

看起来我一直在接受答案时跳过枪。我应该先测试一下。这绝对有效,但不针对IQueryable 。表达式树应该被翻译成一个SQL表达式。这意味着这个LINQ语句不能调用另一个函数,所有相关的数据必须包含在表达式中才能使SQL翻译起作用。一个.ToList()会使它工作,但会牺牲在数据源中执行查询的能力。尽管谢谢你的回答! – Chev 2011-05-25 18:31:48

2

是的,我相信这是做到这一点的正确方法。因为在不重复整个查询部分的情况下创建复杂查询很容易。

而你关于转换为SQL的想法也是正确的。但要小心,这是在数据或聚合被请求时完成的。在你的情况下,当你调用Count()时,SQL将被生成并执行。

+0

太棒了。是的,只要它在完整查询构建完成后执行,那么我很好。我不喜欢在我的存储库上返回'IQueryable '。我更喜欢给我的存储库更详细的方法,比常规存储库做更多的工作。这种方式没有延迟加载问题:) – Chev 2011-05-25 05:43:47