【问题标题】:Why SequenceEqual for List<long> catch error?为什么 List<long> 的 SequenceEqual 捕获错误?
【发布时间】:2020-09-02 13:46:02
【问题描述】:

我有一个名为 schoolrep 的对象,这个 schoolrep 包含许多教育级别 ID 我的 linq 查询给我错误

指定的过滤条件无效

我将发送教育级别 ID 列表,我需要返回具有过滤器中发送的所有教育级别的学校代表

以下是过滤器,我正在尝试使其固定值进行测试

            List<long> lst = new List<long> { 1, 2, 3 };

下面是表达式

            Expression <Func<SchoolRepresentative, bool>> filterExpression = x =>
            x.SchoolRepEducationLevels.Select(x=>x.EducationLevelId).SequenceEqual(lst)

【问题讨论】:

  • 简答 - 不支持。
  • 我该如何处理这个问题
  • 在概念层面上,要意识到编写 SQL 来做到这一点是很困难的。然后,一旦您接受这一点,请意识到这就是不支持它的原因。 :)
  • 在实践中,这意味着您可能需要在内存中而不是在数据库中执行此操作(即全部拉下,然后在本地进行 SequenceEqual)。
  • 具有过滤器中发送的所有教育级别的学校代表,但SequnceEquals 不这样做,它做得更多。

标签: c# .net-core entity-framework-core linq-to-entities


【解决方案1】:

这意味着EF在将查询转换为SQL时不支持SequenceEquals方法。

我不知道是否有等效的紧凑 SQL 查询(查找其唯一子对象 ID 为 1、2 和 3 的所有对象)。

一种选择是使用x =&gt; lst.Contains(x.EducationLevelId) 作为过滤器加载所有具有 1、2 或 3 子级的对象,然后使用任何方法检查内存中是否存在 all 级别你想要的方法。

【讨论】:

    【解决方案2】:

    使用LINQKit,您可以创建一个扩展方法,该方法将转换为测试表达式的SQL。

    public static class IQueryableExt { // using LINQKit
        // searchTerms - IEnumerable<TSearch> where all must match for a row
        // testFne(row,searchTerm) - test one of searchTerms against a row
        // r => searchTerms.All(s => testFne(r,s))
        public static Expression<Func<T, bool>> AllAre<T, TSearch>(this IEnumerable<TSearch> searchTerms, Expression<Func<T, TSearch, bool>> testFne) {
            var pred = PredicateBuilder.New<T>();
            foreach (var s in searchTerms)
                pred = pred.And(r => testFne.Invoke(r, s));
    
            return (Expression<Func<T, bool>>)pred.Expand();
        }
    
        // searchTerms - IEnumerable<TSearch> where one must match for a row
        // testFne(row,searchTerm) - test one of searchTerms against a row
        // r => searchTerms.All(s => testFne(r,s))
        public static Expression<Func<T, bool>> AnyIs<T, TSearch>(this IEnumerable<TSearch> searchTerms, Expression<Func<T, TSearch, bool>> testFne) {
            var pred = PredicateBuilder.New<T>();
            foreach (var s in searchTerms)
                pred = pred.Or(r => testFne.Invoke(r, s));
    
            return (Expression<Func<T, bool>>)pred.Expand();
        }
    }
    

    假设您不需要SequenceEquals,但只包含所有lst,您现在可以使用AllAre 创建过滤器表达式:

    var filterExpression = lst.AllAre((SchoolRepresentative sr, long l) => sr.SchoolRepEducationLevels.Select(srel => srel.EducationLevelId).Contains(l));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-20
      • 1970-01-01
      • 2017-02-18
      • 2016-08-15
      • 2018-11-21
      相关资源
      最近更新 更多