为了账号安全,请及时绑定邮箱和手机立即绑定

使用 IEnumerable 中的属性值从 DbSet<TEntity> 获取所有实体

使用 IEnumerable 中的属性值从 DbSet<TEntity> 获取所有实体

C#
慕斯王 2021-12-05 16:19:56
这看起来真的很简单,但我似乎无法解决它。使用 EF Core,DbSet<Rule> Rules我的DbContext.public class Rule{    public int Id { get; set; }    public string Raw { get; set; }}我正在尝试编写一个查询,其中,给定一个IEnumerable<string> lines,Rule从DbSet它的Raw值是其中一个元素的位置lines(完全匹配,而不是值的子字符串)中给我所有的s 。有一段时间,我使用了类似的东西:private IQueryable<Rule> GetExistingRules() =>    dbContext.Rules.Where(r => lines.Contains(r.Raw));但是,此后我发现(我认为)这并没有达到我的预期。(此方法紧随其后的Rule是为lines当前不存在的所有元素插入 new s 。我得到了Rule具有相同Raw值的重复s ...)我认为,相反,我需要使用.Intersect()?我尝试根据this使用自定义 EqualityComparer ,但它引发了异常。    private IQueryable<Rule> GetExistingRules()    {        var lineRules = lines.Select(l => new Rule {Raw = l});        return dbContext.Rules.Intersect(lineRules, new RuleRawEqualityComparer());    }    private class RuleRawEqualityComparer : IEqualityComparer<Rule>    {        public bool Equals(Rule x, Rule y) => x?.Raw == y?.Raw;        ...    }无法解析表达式 'value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[FilterLists.Data.Entities.Rule]).Intersect(__p_0, __p_1)':方法 'System.Linq.Queryable.Intersect 的重载' 目前不支持。编写此查询的最佳方法是什么?请注意,它处于DbContext交互链中,因此我更愿意将返回类型保留为 anIQueryable以启用 EF 的延迟查询组合。
查看完整描述

2 回答

?
拉风的咖菲猫

TA贡献1995条经验 获得超2个赞

不要忘记,当您将 linQ 与 EFCore 和 IQueryable 一起使用时,它会转换 Sql 语句中的 c# 代码。


你试过这个吗?


var query = from rule in dbContext.Rules

            join line in lines

                on rule.Raw equals line

            select rule;


查看完整回答
反对 回复 2021-12-05
?
慕侠2389804

TA贡献1719条经验 获得超6个赞

你写了:


给我来自 DbSet 的所有规则,其中它的原始值是行中的一个元素(完全匹配等)


您的第一个解决方案将提供所需的结果:


var requestedRules = dbContext.Rules

   .Where(rule => lines.Contains(rule));

在的话:从收集Rules,只选择那些Rules具有A Raw,等于序列中的值的一个值lines。


我得到了具有相同原始值的重复规则......)


显然,您的源集合具有具有相同原始值的规则!


如果您只想要唯一的原始值,则必须决定如何处理重复项:


Id  Raw

 1  "Hello"

 2  "Hello"

你想要哪一个?首先?最后?两个都?没有任何?任何?


让我们选择 Any:我们将创建具有相同 Raw 值的规则组,并且从每个组中我们取第一个(或者如果你想要最后一个,毕竟我们不在乎。但这有点效率低下。


var result = dbContext.Rules

   .Where(rule => lines.Contains(rule))

   .GroupBy(rule => rule.Raw)

   .Select(group => group.FirstOrDefault());

在的话:从收集Rules,只选择那些Rules具有A Raw,等于序列中的值的一个值lines。从剩余的元素中制作具有相同原始值的规则组。然后从每个 Group 中取出任何元素,例如第一个。


如果您想要所有/仅第一个/仅最后一个,您现在就知道该怎么做。


查看完整回答
反对 回复 2021-12-05
  • 2 回答
  • 0 关注
  • 194 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信