使用 LINQ to return 匹配作为参数传入的列表中所有值的实体列表

Using LINQ to return a list of entities that match all values in a list passed in as a parameter

我有一个名为 Business 的 class,一个名为 Tag 的 class 和一个名为 BusinessTagLink 的 class。

Business 和 Tag 都具有以下 属性:

public virtual IList<BusinessTagLink>? BusinessTagLinks { get; set; }

并且每家企业都通过 BusinessTagLink link编入一个或多个标签 table。

我的 BusinessTagLink class 看起来像这样:

public class BusinessTagLink : BaseEntity
    {
        public int BusinessTagLinkId { get; set; }
        public int BusinessId { get; set; }
        public int TagId { get; set; }
        public virtual Business Business { get; set; }
        public virtual Tag Tag { get; set; } 
    }

我正在尝试构建一个过滤器,允许用户通过与标签列表交互来过滤企业列表。我到目前为止有这个:

public static IQueryable<Business> Filter(this IQueryable<Business> businesses, List<int> tagIds)
        {
            if (tagIds.Count == 0)
                return businesses;

            return businesses.Where(x => x.BusinessTagLinks.Any(y => tagIds.Contains(y.TagId)));
        }

如果我想要 return 任何业务标签 link 标签 ID 与作为参数传入的任何标签 ID 相匹配的企业,这非常有用。但是,我希望它 return 只是将所有标签 ID 作为参数传入的企业。例如:

企业 A link 通过企业标签 links table 被编入标签 ID 1、2 和 3。业务 B linked 到标签 2 和 3。在传递 1、2 的列表后,我只希望过滤器到 return 业务 A。

我正在使用 Entity Framework Core 6.0.1,我的数据库是 SQL 服务器。

没有真正测试它 :D 希望它有效 :D

public static IQueryable<Business> Filter(this IQueryable<Business> businesses, List<int> tagIds)
{
    if (tagIds.Count == 0)
        return businesses;

    foreach (var tagId in tagIds)
        businesses = businesses.Where(e => e.BusinessTagLinks.Any(l => l.TagId == tagId));

    return businesses;
}

此外,您的 BusinessTagLink table 不需要具有自动递增主键,因为唯一标识符可以从 BusinessId 和 TagId 派生,具有复合 PK 更有意义

  1. 它将自动在这两列上创建索引
  2. 您将确保不会意外插入无效记录,因为您的数据库中应该始终只有一个 Business-Tag link 实例