实体框架查询以逗号分隔的字段

问题描述 投票:1回答:4

我有一个名为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',则应返回所有具有这些至少这2个标记的条目。

我无法想象我将如何实现这一点。我知道如何使用存储过程实现这一点,这是我的计划b。

c# sql-server asp.net-mvc entity-framework
4个回答
5
投票

存储过程实际上是一个很好的选择,如果不是最好的选择,真的。但是,您仍然可以使用Contains实现它:

var articles = db.Articles.Where(m => tags.Any(t => m.Tags.Contains(t)));

这样做基本上是迭代传入的标签,并创建一个查询,测试Tags是否相似。请记住,因为这将是一个LIKE查询,它将是sloooooowwwww,除非你的Tags列被索引,这也需要是一个定义的长度,而不是像NVARCHAR(MAX)。

另一个潜在的问题是假匹配。假设您有标签“Read”和“Reading”,因为这是一个LIKE查询,搜索“Read”标签将返回两者。实际上,解决这个问题的唯一方法是在数据中添加标记分隔符,例如:“[Read],[Reading]”。然后,您搜索而不是“[Read]”而不是“Read”,并且您保证只撤回正确的。

当我需要打包/解压这样的字符串时,我通常会做类似的事情:

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; }

这看起来相当复杂,但所有这一切都是setter正在解析分隔符上的标签列表,删除我选择使用的短语分隔字符,[]。 getter将列表打包回一个包含所有内容的字符串。

这使您可以使用TagsList,字符串版本将自动保留,而无需考虑它。但是,在查询时,您仍然需要查询Tags,因为这是实际的数据库支持的属性。


0
投票

由于没有允许在查询中进行解析的构造,因此可以使用以下技巧

var query = db.Articles
    .Where(article => tags.All(tag => ("," + article.Tags + ",").Contains("," + tag + ",")))
    .ToList();

它通过使用string.ContainsEnumerable.All构造来检查表字段是否包含所有传递的标记基本上与解析相反。要正确处理字符串中的第一个/最后一个标记,需要在开头/结尾连接逗号。


0
投票

如何在列中使用逗号分隔数据的多个数据。

例如:Ienumerable<string> searchItems ---它会列出A,B,C表,列有订阅---有数据说“E,A,R,C,B,D,H”

因此我们需要谓词生成查询,其中where子句具有搜索生成查询,如下所示:

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)));


-1
投票

你需要一个csv parser.实体框架应该只让你的字段(标签)作为字符串变量。然后,解析器将能够将该单个字符串拆分为List List。

© www.soinside.com 2019 - 2024. All rights reserved.