c# - Linq 2 Sql 使用 'Like' 将本地序列与查询进行比较 - 最有效的方法

标签 c# sql-server linq linq-to-sql

我知道这里有几个类似的问题,关于使用 Sql“Like”操作作为比较器将列表与查询进行比较。

我所知道的是,没有使用 Linq2Sql 进行此类比较的直接翻译。提供的方法 Contains() 转换为 Sql 中的“IN”,并且是一个精确的比较器。我还知道非精确比较方法(SqlMethods.Like()、String.Contains()、StartsWith() 和 EndsWith())都适用于单个项目,而不是列表。

目前,我在 foreach 循环内进行查询以提供所需的功能,但是,我担心网络带宽以及大型循环对数据库服务器的压力。

我的问题是:执行此操作最有效的方法是什么,同时最大限度地减少网络/服务器负载?

我当前实现的代码片段:

using (var context = new GeoDataContext())
{
    var originalSuggestions = new List<SuggestItem>();
    foreach (var suggestItem in suggestionList)
    {
        var item = suggestItem;
        var placeNameList = context.tl_2014_39_places.Where(placeName =>
                       placeName.NAME.Contains(item.Term)).Select(
                           place => place.NAME).ToList();
   }
}

最佳答案

如果您确实需要性能,在这种情况下您应该使用原始 SQL 查询。即使这样,它也不会 super 容易(同样,如果你需要性能的话)。您必须像这样创建自定义类型:

CREATE TYPE dbo.StringList AS TABLE (value NVARCHAR(MAX));

然后在 C# 代码中将这种类型的变量(即 @terms)声明为 DataTable,然后执行类似的操作

select NAME from tl_2014_39_places pl where exists (select 1 from @terms where pl.NAME like '%' + value + '%') 

或使用 @terms 变量加入您的表。然后执行 SqlCommand,您将在一个查询中获得结果。如果您决定遵循原始 sql 查询的路线,我可以帮助您找到正确的高效查询(上面的查询只是其外观的示例)。

更新:这是完整的工作示例。它假设存在带有 NAME 列的表 tl_2014_39_places,并且您使用上面的查询创建了自定义类型 StringList:

private static void Main(string[] args) {
        var termsTable = new DataTable();
        var suggestionList = new List<string>() {"one", "two", "three"};
        termsTable.Columns.Add(new DataColumn("value", typeof (string)));
        foreach (var term in suggestionList) {
            termsTable.Rows.Add(term);
        }
        using (var conn = new SqlConnection(@"data source=(LocalDb)\v11.0;initial catalog=TestDB;integrated security=True;")) {
            conn.Open();
            using (var cmd = new SqlCommand("select NAME from tl_2014_39_places pl where exists (select 1 from @terms where pl.NAME like '%' + value + '%') ", conn)) {
                cmd.Parameters.Add(new SqlParameter("terms", SqlDbType.Structured) {
                    Value = termsTable,                        
                    TypeName = "dbo.StringList"
                });
                using (var reader = cmd.ExecuteReader()) {
                    while (reader.Read()) {
                        Console.WriteLine(reader[0]);
                    }
                }
            }
        }
        Console.ReadKey();
    }

请注意,一般来说,带有第一个“%”的 LIKE(即“以”结尾的查询)效率较低,因为需要扫描整个表才能获取结果。但这与问题本身无关,当然它仍然比循环和多个数据库查询更有效。您还可以使用以下等效查询来代替 whereexists:

select NAME from tl_2014_39_places pl inner join @terms t on pl.NAME like '%' + t.value + '%'

关于c# - Linq 2 Sql 使用 'Like' 将本地序列与查询进行比较 - 最有效的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32462869/

相关文章:

entity-framework - 在 EF Core 中,如何执行分组并选择逗号分隔值列表?

c# - 如何获取一个类型的所有公共(public)(获取和设置)字符串属性

c# - 使用反射设置索引属性的值

c# - 使用 EnableModelValidation 时如何验证 FormView 数据?

sql - 在自引用表中查找最上面的 parent

c# - 如何在不枚举查询的情况下将 string 转换为 int

c# - 无法理解此 Func<in T, out T> 应如何与 Url.Action 委托(delegate)一起使用

sql-server - 带通配符的 sp_help

.net - 如何将 XML 从 SQL Server 2005 流式传输到 HTTP 响应流以供下载

c# - C#将序列号应用于组项目