Linq to SQL如何做“(值列表中)[列]的位置”


101

我有一个获取ID列表的函数,我需要返回一个与ID关联的描述匹配的列表。例如:

public class CodeData
{
    string CodeId {get; set;}
    string Description {get; set;}
}

public List<CodeData> GetCodeDescriptionList(List<string> codeIDs)
    //Given the list of institution codes, return a list of CodeData
    //having the given CodeIds
}

因此,如果我自己为此创建sql,则只需执行以下操作(其中in子句包含codeIds参数中的所有值):

Select CodeId, Description FROM CodeTable WHERE CodeId IN ('1a','2b','3')

在Linq to Sql中,我似乎找不到等效的“ IN”子句。到目前为止,我发现最好的(不起作用)是:

 var foo = from codeData in channel.AsQueryable<CodeData>()
           where codeData.CodeId == "1" || codeData.CodeId == "2"
           select codeData;

问题是,我无法为linq to sql动态生成“ OR”子句的列表,因为它们是在编译时设置的。

如何使用Linq to Sql完成在动态值列表中检查列的where子句?

Answers:


159

where list.Contains(item.Property)

或您的情况:

var foo = from codeData in channel.AsQueryable<CodeData>()
          where codeIDs.Contains(codeData.CodeId)
          select codeData;

但是您也可以用点表示法来做到这一点:

var foo = channel.AsQueryable<CodeData>()
                 .Where(codeData => codeIDs.Contains(codeData.CodeId));

CodeId是Integer的情况下如何使用?
基兰·索卡

2
@KiranSolkar:那么大概codeIDsList<int>,一切都会好起来的。
乔恩·斯基特

@JonSkeet区分大小写吗?如果codeIDs是大写字符串列表,而codeData.codeId是小写字符串,则它将失败。
PersyJack '17

@PersyJack:关于它必须不区分大小写,没有任何问题。至于是否会这样,我不记得默认情况下LINQ to SQL是强制区分大小写还是由db设置来控制它。
乔恩·斯基特

1
@PersyJack LINQ to SQL生成T-SQL查询,然后使用区分大小写的数据库设置在SQL Server上运行。虽然,如果不小心,并实现查询结果,则在将LINQ应用于内存中对象之前,它们可能会遭受大小写敏感性不匹配的后果。
Zarepheth

26

您还可以使用:

List<int> codes = new List<int>();

codes.add(1);
codes.add(2);

var foo = from codeData in channel.AsQueryable<CodeData>()
          where codes.Any(code => codeData.CodeID.Equals(code))
          select codeData;

1
由于我们的IQToolkit实现不支持.Contains()
DJ van Wyk

1

我一直在使用Jon Skeet的答案中的方法,但是使用出现了另一个方法ConcatConcat在有限的测试中,该方法的性能稍好一些,但这很麻烦,我可能会坚持使用Contains,或者我会写一个辅助方法来帮助我。无论哪种方式,如果有人感兴趣,这是另一个选择:

方法

// Given an array of id's
var ids = new Guid[] { ... };

// and a DataContext
var dc = new MyDataContext();

// start the queryable
var query = (
    from thing in dc.Things
    where thing.Id == ids[ 0 ]
    select thing 
);

// then, for each other id
for( var i = 1; i < ids.Count(); i++ ) {
    // select that thing and concat to queryable
    query.Concat(
        from thing in dc.Things
        where thing.Id == ids[ i ]
        select thing
    );
}

性能测试

这不是遥不可及的科学。我想您的数据库结构和列表中涉及的ID数量将产生重大影响。

我设置了一个试验,其中我做的每100次试验ConcatContains其中,每个试验包括选择由主键的随机化列表中指定的25行。我已经运行了大约12次,大多数情况下该Concat方法的速度提高了5-10%,尽管该Contains方法仅次于smidgen赢得了。


0
 var filterTransNos = (from so in db.SalesOrderDetails
                    where  ItemDescription.Contains(ItemDescription)
                            select new { so.TransNo }).AsEnumerable();    


listreceipt = listreceipt.Where(p => filterTransNos.Any(p2 => p2.TransNo == p.TransNo)).ToList();

-1

这是我使用HashSet的方法

        HashSet<String> hs = new HashSet<string>(new String[] { "Pluto", "Earth", "Neptune" });
        String[] arr =
        {
            "Pluto",
            "Earth",
            "Neptune",
            "Jupiter",
            "Saturn",
            "Mercury",
            "Pluto",
            "Earth",
            "Neptune",
            "Jupiter",
            "Saturn",
            "Mercury",
            // etc.
        };
        ICollection<String> coll = arr;

        String[] arrStrFiltered = coll.Where(str => hs.Contains(str)).ToArray();

HashSet基本上接近O(1),因此您的复杂度仍然为O(n)。


这是关于LINQ-to-SQL。此类LINQ到对象的注意事项不适用。
Gert Arnold

ICollection的可能来自LINQ-SQL也是如此,这是一个通用的方法
MG

问题是关于如何构建可转换为正确SQL的表达式。这与如何搜索本地集合无关。您的答案只会欺骗那些不知道这种区别的未来读者。
Gert Arnold
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.