如何重构LINQ查询以使用委托或表达式<;Func<;T、 bool>>;

本文关键字:lt gt 表达式 Func bool 重构 何重构 LINQ 查询 | 更新日期: 2023-09-27 18:21:27

此方法非常有效,只生成1个查询(使用.Includes()进行预加载)。然而,我想重构AbleToDelete代码,使其更加可重用。(使用EF4)

        public override IEnumerable<AffectProjection> SelectAll(SearchAffects page)
        {
            IQueryable<Affect> query = BuildSearchQuery(page);
            IEnumerable<AffectProjection> results = query.Select(entity => new AffectProjection()
            {
                AffectID = entity.AffectID,
                AffectCode = entity.AffectCode,
                AffectName = entity.AffectName,
                AbleToDelete = !((entity.Foo1s.Any(pa => !pa.Inactive))
                                || (entity.Foo2s.Any(ea => !ea.Inactive))
                                || (entity.Foo3s.Any(sa => !sa.Inactive))
                                || (entity.Foo4s.Any(spa => !spa.Inactive)))
            }).ToArray();
            return results;
        }

我把代码移到了Expression Func结构中,但不知道如何替换设置AbleToDelete属性的代码。劝告

public Expression<Func<Affect, bool>> DelegateExpression = entity =>
            !((entity.Foo1s.Any(pa => !pa.Inactive))
                || (entity.Foo2s.Any(ea => !ea.Inactive))
                || (entity.Foo3s.Any(sa => !sa.Inactive))
                || (entity.Foo4s.Any(spa => !spa.Inactive)));

最后但同样重要的是,此解决方案编译但在运行时失败,错误为:"NotSupportedException-LINQ to Entities中不支持LINQ表达式节点类型"Invoke"。"尝试使用不支持的委托:

        public override IEnumerable<AffectProjection> SelectAll(SearchAffects page)
        {
            IQueryable<Affect> query = BuildSearchQuery(page);
            //Create delegate instance and register method -- single statement
            var deleteAbilityAllowed = new CanDelete(GetAbleToDelete);
            IEnumerable<AffectProjection> results = query.Select(entity => new AffectProjection()
            {
                AffectID = entity.AffectID,
                AffectCode = entity.AffectCode,
                AffectName = entity.AffectName,
                AbleToDelete = deleteAbilityAllowed(entity)
            }).ToArray();
            return results;
        }
        public delegate bool CanDelete(Affect entity);
        public bool GetAbleToDelete(Affect entity)
        {
            return !((entity.Foo1s.Any(pa => !pa.Inactive))
                || (entity.Foo2s.Any(ea => !ea.Inactive))
                || (entity.Foo3s.Any(sa => !sa.Inactive))
                || (entity.Foo4s.Any(spa => !spa.Inactive)));
        }

请提前告知并感谢!

如何重构LINQ查询以使用委托或表达式<;Func<;T、 bool>>;

LINQKit包含允许您执行此操作的方法。有了它,您就可以使用yout DelegateExpression。为此,将AsExpandable()添加到查询源,然后使用Invoke():调用表达式

var expression = DelegateExpression;
var results = query.AsExpandable().Select(entity => new AffectProjection()
{
    AffectID = entity.AffectID,
    AffectCode = entity.AffectCode,
    AffectName = entity.AffectName,
    AbleToDelete = expression.Invoke(entity)
}).ToArray();

不过要小心,似乎不能直接从字段中使用表达式,它必须来自局部变量。