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

时间:2016-02-12 16:31:19

标签: c# sql-server asp.net-mvc entity-framework

我有一个名为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。

4 个答案:

答案 0 :(得分:5)

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

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

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

另一个潜在问题是错误匹配。让我们说你有标签,&#34;阅读&#34;和&#34;阅读&#34;,因为这是一个LIKE查询,搜索&#34; Read&#34;标签,将返回两者。实际上,解决这个问题的唯一方法是在数据中添加标记分隔符,例如:&#34; [读取],[阅读]&#34;。然后,您搜索而不是&#34; [Read]&#34;,而不是&#34; Read&#34;,并且您保证只撤回正确的。

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

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正在解析分隔符上的标记列表,删除了我选择使用的短语分隔字符,[和{{ 1}}。 getter将列表打包回一个字符串中。

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

答案 1 :(得分:0)

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

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

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

答案 2 :(得分: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)));

答案 3 :(得分:-1)

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