如何重构LINQ查询以使用委托或表达式<func <t,bool =“”>&gt; </func <t,>

时间:2012-01-26 16:58:37

标签: c# linq entity-framework-4 lambda

此方法效果很好,只生成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)));
        }

请提前告知并谢谢你!

1 个答案:

答案 0 :(得分:2)

LINQKit包含允许您执行此操作的方法。有了它,您可以使用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();

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