gpt4 book ai didi

c# 使用 Linq2Sql 在表列中查找匹配词

转载 作者:行者123 更新时间:2023-11-30 18:09:12 25 4
gpt4 key购买 nike

我正在尝试使用 Linq2Sql 返回包含字符串列表中的值的所有行。 linq2sql 类对象有一个字符串属性,其中包含由空格分隔的单词。

public class MyObject
{
public string MyProperty { get; set; }
}

示例 MyProperty 值是:

MyObject1.MyProperty = "text1 text2 text3 text4"
MyObject2.MyProperty = "text2"

例如,使用字符串集合,我传递以下列表

var list = new List<>() { "text2", "text4" }

这将返回我上面示例中的两个项目,因为它们都包含“text2”值。

我尝试使用下面的代码执行以下操作,但是由于我的扩展方法无法评估 Linq2Sql。

public static IQueryable<MyObject> WithProperty(this IQueryable<MyProperty> qry,
IList<string> p)
{
return from t in qry
where t.MyProperty.Contains(p, ' ')
select t;
}

我也写了一个扩展方法

public static bool Contains(this string str, IList<string> list, char seperator)
{
if (str == null) return false;
if (list == null) return true;

var splitStr = str.Split(new char[] { seperator },
StringSplitOptions.RemoveEmptyEntries);

bool retval = false;
int matches = 0;

foreach (string s in splitStr)
{
foreach (string l in list)
{
if (String.Compare(s, l, true) == 0)
{
retval = true;
matches++;
}
}
}

return retval && (splitStr.Length > 0) && (list.Count == matches);
}

关于如何实现此目标的任何帮助或想法?

最佳答案

您走在正确的轨道上。你的扩展方法的第一个参数 WithProperty必须是 IQueryable<MyObject> 类型, 不是 IQueryable<MyProperty> .

无论如何,您不需要 IQueryable 的扩展方法.只需使用您的 Contains lambda 中用于过滤的方法。这应该有效:

List<string> searchStrs = new List<string>() { "text2", "text4" }

IEnumerable<MyObject> myFilteredObjects = dataContext.MyObjects
.Where(myObj => myObj.MyProperty.Contains(searchStrs, ' '));

更新:

上面的代码片段有效。这是因为 Contains方法不能转换成SQL语句。我对这个问题思考了一会儿,并通过思考“我将如何在 SQL 中执行此操作?”得出了解决方案:您可以通过查询每个关键字并将所有结果合并在一起来实现。遗憾的是,Linq-to-SQL 的延迟执行阻止了在一个查询中完成所有操作。所以我想出了这个妥协中的妥协。它查询每个关键字。这可以是以下之一:

  • 等于字符串
  • 在两个分隔符之间
  • 在字符串的开头,后面跟一个分隔符
  • 或在字符串的末尾并以分隔符开头

这跨越了一个有效的表达式树,并且可以通过 Linq-to-SQL 翻译成 SQL。查询后,我不会通过立即获取数据并将其存储在列表中来推迟执行。之后将所有列表合并。

public static IEnumerable<MyObject> ContainsOneOfTheseKeywords(
this IQueryable<MyObject> qry, List<string> keywords, char sep)
{
List<List<MyObject>> parts = new List<List<MyObject>>();

foreach (string keyw in keywords)
parts.Add((
from obj in qry
where obj.MyProperty == keyw ||
obj.MyProperty.IndexOf(sep + keyw + sep) != -1 ||
obj.MyProperty.IndexOf(keyw + sep) >= 0 ||
obj.MyProperty.IndexOf(sep + keyw) ==
obj.MyProperty.Length - keyw.Length - 1
select obj).ToList());

IEnumerable<MyObject> union = null;
bool first = true;
foreach (List<MyObject> part in parts)
{
if (first)
{
union = part;
first = false;
}
else
union = union.Union(part);
}

return union.ToList();
}

并使用它:

List<string> searchStrs = new List<string>() { "text2", "text4" };

IEnumerable<MyObject> myFilteredObjects = dataContext.MyObjects
.ContainsOneOfTheseKeywords(searchStrs, ' ');

这个解决方案真的很不优雅。对于 10 个关键字,我必须查询数据库 10 次,每次都捕获数据并将其存储在内存中。这是在浪费内存并且性能很差。我只是想证明它在 Linq 中是可能的(也许它可以在这里或那里进行优化,但我认为它不会变得完美)。

我强烈建议将该函数的逻辑交换到数据库服务器的存储过程中。一个查询,由数据库服务器优化,不浪费内存。

另一种选择是重新考虑您的数据库设计。如果你想查询一个字段的内容(你把这个字段当作一组关键字,用空格分隔),你可能只是选择了一个不合适的数据库设计。您宁愿创建一个带有表外键的新表。新表只有一个关键字。查询会更简单、更快且更易于理解。

关于c# 使用 Linq2Sql 在表列中查找匹配词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2616751/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com