实体框架查询逗号分隔的字段
本文关键字:分隔 字段 框架 查询 实体 | 更新日期: 2023-09-27 18:34:26
我有一个名为Article的表:
-Id
-Title
-Content
-Tags (This is a comma seperated list of tags e.g. 'Sports,Italy,Ferrari')
使用实体框架,我希望能够找到具有某些标签的所有文章。
List<Article> GetArticles(List<String> tags)
{
//do an entity framework query here to find all articles which have the tags specified
}
返回的条目应包含指定的所有标记。例如,如果函数的输入是"car","blue",则应返回至少具有这两个标签的所有条目。
我无法想象我如何实现这一点。 我知道如何使用存储过程来实现这一点,这是我的计划b。
存储过程实际上是一个不错的选择,如果不是最好的选择,真的。但是,您仍然可以通过以下方式实现它 Contains
:
var articles = db.Articles.Where(m => tags.Any(t => m.Tags.Contains(t)));
这样做基本上是遍历传入的标签,并创建一个查询来测试Tags
是否与其中任何一个相似。请记住,因为这将是一个 LIKE 查询,所以它将是 slooooowwwww,除非您的Tags
列被索引,这也要求它是一个定义的长度,而不是像 NVARCHAR(MAX( 这样的东西。
另一个潜在问题是错误匹配。假设你有标签,"读取"和"阅读",因为这是一个 LIKE 查询,搜索"读取"标签,将返回两者。实际上,解决此问题的唯一方法是向数据添加标记分隔符,例如:"[读取],[读取]"。然后,您搜索而不是"[读取]"而不是"读取",并且保证只拉回正确的一个。
当我需要像这样打包/解压缩字符串时,我通常会执行以下操作:
public string Tags
{
get
{
return TagsList != null
? String.Join(",", TagsList.Select(tag => "[" + tag + "]"))
: null;
}
set
{
TagsList = !String.IsNullOrWhiteSpace(value)
? value.Replace("[", "").Replace("]", "").Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).ToList()
: new List<string>();
}
}
[NotMapped]
public List<string> TagsList { get; set; }
这看起来相当复杂,但所发生的事情是,二传手正在解压缩分隔符上的标签列表,删除我选择使用的短语分隔字符,[
和]
。getter 将列表打包回一个包含所有这些的字符串中。
这允许您只使用TagsList
字符串版本将自动保留,而无需考虑它。但是,在查询时,您仍然必须查询 Tags
,因为这是实际的数据库支持的属性。
由于没有允许在查询内部解析的构造,因此可以使用以下技巧
var query = db.Articles
.Where(article => tags.All(tag => ("," + article.Tags + ",").Contains("," + tag + ",")))
.ToList();
它基本上通过使用字符串检查表字段是否包含所有传递的标签来执行与解析相反的操作。包含和枚举。EF 都支持的所有构造。需要在开头/结尾连接逗号,以正确处理字符串中的第一个/最后一个标签。
具有逗号分隔数据的列中获取多个数据。
例如:Ienumerable<string> searchItems
---它会列出 A、B、C带有列的表 订阅---数据显示"E,A,R,C,B,D,H">
所以我们需要谓词来生成查询,其中子句具有搜索以生成查询为:
WHERE Subscribe LIKE'%A%' OR LIKE'%B%' OR LIKE'%C%'
目前它生成:
WHERE Subscribe LIKE'%A%' AND LIKE'%B%' AND LIKE'%C%'
当我们尝试时 - searchItems.ForEach(y => query = query.Where(y => y.Subscribe.Contains(y)));
你需要一个csv解析器。实体框架应仅将字段(标记(作为字符串变量获取。然后,解析器将能够将该单个字符串拆分为列表标记。