【问题标题】:LINQ query with EF Core to find records with matching items from many-to-many relationship使用 EF Core 进行 LINQ 查询以从多对多关系中查找具有匹配项的记录
【发布时间】:2020-10-08 10:04:27
【问题描述】:

我对 .NET 和 EF Core 还很陌生,我正在构建一个分类列表类型的应用程序。我想比较记录并根据标签(通过实体框架中的多对多关系链接)找到匹配的通缉/待售分类。

首先,我试图确保用户没有尝试添加重复的列表。我花了非常多的时间试图弄清楚如何编写查询,但我尝试的所有事情都在运行时出现异常,我觉得我在一遍又一遍地尝试同样的事情。

我认为这个查询应该可以工作,但我不知道为什么它不工作,它构建时没有任何错误,但在运行时出现“指定的过滤条件无效”的异常:

public bool IsDuplicate(Classified classified)
{
    var idSet = classified.ClassifiedTags.Select(ct => ct.Tag.Id).ToHashSet<int>();
    var query = from c in _context.Classified 
                where c.ClassifiedTags.Select(ct => ct.Tag.Id).ToHashSet<int>().SetEquals(idSet) &&
                      c.User == classified.User
                select c;

    // .... return true if a record is found
}

这些表在 EF Core 中设置了多对多连接:Classified ClassifiedTag Tag

我的 ApplicationDbContext 看起来像这样

public DbSet<Tag> Tags { get; set; }
public DbSet<Classified> Classified { get; set; }
public DbSet<ClassifiedTag> ClassifiedTags { get; set; }

protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);
    builder.Entity<Tag>().ToTable("Tag");
    builder.Entity<ClassifiedTag>().ToTable("ClassifiedTag");

    builder.Entity<ClassifiedTag>()
        .HasKey(ct => new { ct.ClassifiedId, ct.TagId });

    builder.Entity<ClassifiedTag>()
        .HasOne(c => c.Classified)
        .WithMany(ct => ct.ClassifiedTags)
        .HasForeignKey(ct => ct.ClassifiedId);

    builder.Entity<ClassifiedTag>()
        .HasOne(t => t.Tag)
        .WithMany(ct => ct.ClassifiedTags)
        .HasForeignKey(ct => ct.TagId);
}

我的分类模型如下所示:

public class Classified
{
    public Guid Id { get; set; }
    public int Type { get; set; }
    public ApplicationUser User { get; set; }
    public DateTime DateCreated { get; set; }
    public List<ClassifiedTag> ClassifiedTags { get; set; }
}

public class ClassifiedTag {
    public Guid ClassifiedId { get; set; }
    public Classified Classified { get; set; }
    public int TagId { get; set; }
    public Tag Tag { get; set; }
}

我的 Tag 模型如下所示:

public class Tag
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<ClassifiedTag> ClassifiedTags { get; set; }
}

我觉得这应该很简单,但在这一点上我真的被困住了,任何帮助都将不胜感激!

【问题讨论】:

  • 你能用文字解释你想要达到的目标吗?你指的这个“清单”是什么?就您的实体名称而言,用户试图添加什么? ClassifiedTag?试着告诉我这个故事:)
  • 对不起,我应该更清楚。用户正在尝试通过ClassifiedTag 加入表添加与Tag 具有多对多关系的Classified。我正在尝试检查是否存在包含相同 Tag 记录集合的现有 Classified
  • 所以如果ClassifiedClassifiedTag 链接,那么您希望IsDuplicate 返回true?那么如果Classified.UserClassified.Type 存在但ClassifiedTag 链接不存在,IsDuplicate 是否应该返回false

标签: c# linq asp.net-core entity-framework-core ef-core-3.0


【解决方案1】:

在您的查询中ToHashSet&lt;int&gt;() 无法转换为 SQL 并发生异常。

【讨论】:

  • “你可以把所有的数据都带入内存”听起来不太好,对吧?这就是在 EFC 3.0+ 中删除客户端评估的全部原因。
  • 有道理,我忘了幕后发生了什么。
  • 一旦我返回了所有记录,我已经设法过滤了连接表上的结果,但是加载可能数千条记录然后过滤它们似乎是个坏主意。我觉得如果可能的话,最好在查询级别进行过滤,所以我只需要从数据库中返回我想要的结果。
  • 返回所有数据是非常糟糕的做法。除非您使用某种缓存系统,并且这只在启动时触发,或者在刷新缓存请求时触发。
  • 真的很烦人,错误信息并没有表明ToHashSet()是罪犯...
猜你喜欢
  • 2021-10-21
  • 2019-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-20
  • 2023-03-22
相关资源
最近更新 更多