【问题标题】:LINQ to SQL many to many, containsLINQ to SQL 多对多,包含
【发布时间】:2009-08-19 21:41:48
【问题描述】:

我有以下数据库(简体)

图片 - ImageTag - 标签

ImageTag 是一个连接表,用于形成多对多关系。

我想创建一个方法来返回所有包含 x 标签的图像,这就是我开始的:

public static IQueryable<Image> WithTags(this IQueryable<Image> qry, IEnumerable<Tag> tags)
{
    return from i in qry //uhhhh
}

但是如你所见,我有点难过!

我知道如何使用普通 SQL 来完成,但我对 LINQ 语法有点困惑,有什么想法吗?

--

编辑

它应该匹配具有任何标签的任何图像

所以例如,如果在“qry”变量中,有一个带有标签1,2,3的图像......如果你传入标签变量1和2,它将匹配

类似,如果你通过了 1,2,4 - 即使它没有 4,它也应该仍然匹配

如果你通过了 3 和 4,它也会匹配


编辑 2

如果它可以按照匹配的数量对返回的图像进行排序,那就太棒了。因此,例如,如果您传入 3 个标签并且一张图片包含所有 3 个标签,那么它会比只匹配 1 个标签的图片更高

【问题讨论】:

  • 你的意思是有所有的x标签,还是其中任何一个?
  • 任何一个,都会澄清这个问题......
  • 如果您通过标签 3 和 4,标签为 1、2、3 的图像是否匹配?
  • 是的,它会匹配,基本上只是在寻找任何类型的匹配。如果您可以按比赛数量排序,您将获得金星:p

标签: c# linq-to-sql


【解决方案1】:

我假设您在 Image 上设置了关系以访问其 ImageTags - 如果没有,您可以使用 join 子句。

您可以在您的(小型)本地集合上使用Contains 将这些值传递给服务器:

return from i in qry
       from it in i.ImageTags
       where tags.Contains(it.Tag)
       select i;

您可能需要使用密钥而不是 Tag 实体:

       where tags.Select(t => t.ID).Contains(it.Tag.ID)

另请参阅:Creating IN Queries With Linq To Sql


您可以使用group by 子句来计算匹配项:

return from i in qry
       from it in i.ImageTags
       where tags.Select(t => t.ID).Contains(it.Tag.ID)
       group new { Image = i, it.Tag } by i.ID into g
       let tagCount = g.Count()
       orderby tagCount descending
       select g.First().Image;

【讨论】:

  • 假设他的意思是带有“x”标签之一的图像?我认为他希望所有这些都匹配。
  • 在选择行上出现此错误:错误 4 在源类型为“System.Linq.IQueryable'。调用“SelectMany”时类型推断失败。
  • 这似乎是在抱怨第二个 from 子句。如果添加“let iTags = i.ImageTags”这样的行,那么 iTags 是什么类型?我希望它是 IQueryable.
  • 添加了一个按匹配标签数量排序的示例组。
【解决方案2】:

假设您要选择提供的标签是图像实际标签的子集(而不是完全匹配)的所有图像,我认为应该这样做:

public static IQueryable<Image> WithTags(this IQueryable<Image> qry, IEnumerable<Tag> tags)
{
    return 
        from i in qry
        from iTags in i.ImageTags.Select(it =>it.Tag)
        where !tags.Except(iTags).Any() //* See below
        select i;

}

*我从以下地方借用了子句: Check whether an array is a subset of another

【讨论】:

  • 好吧,当我尝试第二行的qry,当你做qry。 - 图像标签选择不会出现在智能感知中,只是 IQueryable 上可用的方法。如果您只采用 single Image 对象,它将具有该属性..
  • 另外,除了会期望一个集合,但在这里被传递单个 Tag 对象。需要让 iTags = i.ImageTags.Select(it => it.Tag)。但是,我不相信 LINQ to SQL 会知道如何翻译 except。
  • @dahlbyk 感谢您发现这一点
  • 我相信 iTags 是一个 IQueryable,请注意我使用的是 select,而不是 i.ImageTags.Tag 如果您遇到问题,请告诉我 MSDN 似乎显示除 OK ,但我承认我自己没有使用过:msdn.microsoft.com/en-us/library/bb399342.aspx
  • 你的 Select 确实会返回一个 IQueryable,但是“from iTags in ...”会从中获取每个 Tag。
猜你喜欢
  • 1970-01-01
  • 2019-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多