加入这两个列表的方法是什么?

时间:2013-11-06 11:14:02

标签: c# .net linq linq-to-sql

我有一个IList<User>,其中包含一对值为NameSurname的对象。 在数据库上,我有一个包含Name和Surname字段的行的表。我想在codebehind上返回与我的List匹配的行列表,所以让我们说Name和Surname(分别)等于。

我的实际代码是:

utenti = (from User utente in db.User.AsEnumerable()
          join amico in amiciParsed 
               on new { utente.Nome, utente.Cognome } equals 
                  new { Nome = amico.first_name, Cognome = amico.last_name }
          select utente).OrderBy(p => p.Nome)
                        .OrderBy(p => p.Cognome)
                        .OrderBy(p => p.Nickname)
                        .ToList();

但这有两个原因并不好:

  1. 它将在客户端上下载数据库的全部记录;
  2. 我不能将姓名和姓氏视为区分大小写(例如Marco cordi!= Marco Cordi);在DB上我有各种上/下字符。
  3. 正如之前的问题所示,似乎这个answer无法帮助我,因为我必须做一个连接(并且因为第一个问题与之无关)。

    解决此问题的方法是什么?

3 个答案:

答案 0 :(得分:0)

我不知道这是否适用于您的情况,但您可以尝试一下。

首先,创建一个新的字符串列表:

List<string> amici = aimiciParsed.Select(x => x.first_name + "|" + x.last_name).ToList();

然后,根据此列表

从DB中选择用户
var utenti = db.User.AsEnumerable().Where(utente => 
    amici.Contains(utente.Nome + "|" + utente.Cognome)).ToList();

它将字符串列表作为参数列表发送到DB,并将其转换为类似

的查询
SELECT * FROM User WHERE User.Nome + "|" + User.Cognome IN (@p1, @p2, @p3 ...)

很遗憾,无法使用StringComparison.OrdinalIgnoreCase之类的内容调用Contains,因此您可能需要更改列的排序规则。

答案 1 :(得分:0)

可以使用PredicateBuilder

完成此操作
using LinqKit;

var predicate = PredicateBuilder.False<User>();

foreach(var amico in amiciParsed)
{
    var a1 = amico; // Prevent modified closure (pre .Net 4.5)
    predicate = predicate.Or(user => user.Nome == a1.first_name 
                                  && user.Cognome == a1.last_name);
}

var query = db.User.Where(predicate.Expand())
              .OrderBy(p => p.Nome)
              ...

优点是可以使用NomeCognome上的索引(如果搜索连接值,这是不可能的)。另一方面,OR子句的数量可能会非常大,这可能会在SQL Server(https://stackoverflow.com/a/1869810/861716)中达到某些限制。你必须对此进行压力测试(尽管IN条款也是如此)。

答案 2 :(得分:0)

在SO上提问时,您可能希望将其翻译成英语 - 不要指望人们知道“uente”,“amico”或“Cognome”是什么。

一个问题:为什么使用..in db.User.AsEnumerable()而不只是..in db.User

让查询中的所有内容保持IQueryable(而不是IEnumerable)。这使得Linq2Sql可以创建尽可能优化的SQL,而不是下载所有记录并加入客户端的记录。这也可能是您的搜索区分大小写的原因。客户端内存中字符串比较始终区分大小写,而SQL中的字符串比较取决于数据库的配置。

尝试放弃.AsEnumerable()并查看您是否获得了更好的结果:

utenti = (from User foo in db.User
          join bar in amiciParsed 
          ...