为LINQ TO实体编写可翻译的方法 [英] Write a translatable method for LINQ TO Entities
问题描述
使用实体框架(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屋!