为LINQ TO实体编写可翻译的方法 [英] Write a translatable method for LINQ TO Entities

查看:97
本文介绍了为LINQ TO实体编写可翻译的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用实体框架(LINQ到实体)

Using Entity Framework (LINQ to Entities)

以下工作正常.表达式被翻译成SQL

The following is working just fine. The expressions got translated to SQL

var foos = ctx.Foos.Select(f => new {
   P1 = ctx.Bars.FirstOrDefault(b => b.SomeProp == "Const1" && f.X1 == b.Y),
   P2 = ctx.Bars.FirstOrDefault(b => b.SomeProp == "Const2" && f.X2 == b.Y),
   P3 = ctx.Bars.FirstOrDefault(b => b.SomeProp == "Const3" && f.X3 == b.Y),
}

重复表达式b.SomeProp == "..." && f.X* == b.Y实际上是真实表达式的简化版本,但是如果您可以帮助我,请加以理解.我也会弄清楚其余的...

The repetitive expression b.SomeProp == "..." && f.X* == b.Y is actually a simplified version of the real expression, but if you can help me wit this. I'll figure out the rest as well...

我想写的是这样的东西. (首选)

What I would like to write is something like this. (Preferred)

var foos = ctx.Foos.Select(f => new {
   P1 = f.GetBar("Const1", f.X1),
   P2 = f.GetBar("Const2", f.X2),
   P3 = f.GetBar("Const3", f.X3),
}

但是我也可以用类似的东西

But I might also be fine with something like

P1 = ctx.Bars.GetByFoo(f.X1, "Const1");
- or -
P1 = ctx.Bars.FirstOrDefault(GetByFoo(f.X1, "Const1"))
- or -
P1 = ctx.Bars.GetByFoo(x => x.X1, "Const1");

基于此答案 https://stackoverflow.com/a/2244917/2968001 我到目前为止最接近的是

Based on this answer https://stackoverflow.com/a/2244917/2968001 The closest I came so far is

ctx.Bars.FirstOrDefault(GetByFoo(x => x.Y == f.X1 , "Const1"))

and

private static Expression<Func<Bar, bool>> GetByFoo(Func<Foo, bool> optionSelector, string par1)
    {
        return b => b.SomeProp == par1 && optionSelector(o);
    }

不幸的是,这 a)仍远未达到期望 b)这不起作用:(.它给出了运行时异常:

Unfortunately, this a) Is still far from desired b) this does not work :(. It gives a run-time exception:

从范围''引用的类型为'Foo'的

变量'f',但不是 定义

variable 'f' of type 'Foo' referenced from scope '', but it is not defined

表达式保持可翻译性是至关重要的.我不能检索所有foo,然后为每个foo检索Bar.

It is essential that the expression keeps translatable. I am not fine with retrieving all foos and then retrieving the Bar for each foo.

推荐答案

关于这些方面的事情

public static class Extensions
{
    public static IQueryable<T> Filter<T>(this DemoContext instance, Expression<Func<T, bool>> predicate = null, string value = null)
        where T : class, IMarker
    {
        return instance
            .Set<T>()
            .Where(p => p.SomeProp == value)
            .Where(predicate);
    }
}

应该允许您编写类似的内容

that should allow you to write something like

var inner1 = ctx.Filter<Bar>(value: "Const1");
var inner2 = ctx.Filter<Bar>(value: "Const2");
var inner3 = ctx.Filter<Bar>(value: "Const3");

var query = from foo in ctx.Foos
            select new
            {
                P1 = inner1.FirstOrDefault(p => p.Y == foo.X1),
                P2 = inner2.FirstOrDefault(p => p.Y == foo.X2),
                P3 = inner3.FirstOrDefault(p => p.Y == foo.X3),
            };

IMarker界面仅用于帮助您处理特殊谓词

where the IMarker interface is just to help you deal with specialized predicates

public class Foo : IEntity
{
    public string X1 { get; set; }
    public string X2 { get; set; }
    public string X3 { get; set; }

}

public class Bar : IMarker
{
    public string SomeProp { get; set; }
    public string Y { get; set; }
}

public interface IEntity
{
}

public interface IMarker : IEntity
{
    string SomeProp { get; set; }
}

这篇关于为LINQ TO实体编写可翻译的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆