Sql 动态地将LINQ更改为实体查询
在表达式'ODInfo=>ODInfo.TONS2009'中,如何基于方法参数'int year'将TONS2009更改为TONS2010或TONS2011 您可以尝试类似的方法:Sql 动态地将LINQ更改为实体查询,sql,linq,entity-framework,Sql,Linq,Entity Framework,在表达式'ODInfo=>ODInfo.TONS2009'中,如何基于方法参数'int year'将TONS2009更改为TONS2010或TONS2011 您可以尝试类似的方法: int year = 2009; // get summ of TONS2009 column var query = from ODInfo in DataContext.CIMS_TRUCKS where pLocationIDs.Contains(ODInfo.OID)
int year = 2009; // get summ of TONS2009 column
var query = from ODInfo in DataContext.CIMS_TRUCKS
where pLocationIDs.Contains(ODInfo.OID)
group ODInfo by ODInfo.OID into g
select new
{
OID = g.Key,
TotalTons = g.Sum( ODInfo => ODInfo.TONS2009)
};
或者使其更具可读性,并使用{}
将lambda表达式拆分为多行,然后使用例如switch语句。尝试以下方法:
TotalTons = g.Sum( ODInfo => (year == 2009) ? ODInfo.TONS2009 : ((year == 2010)
? ODInfo.TONS2010 : ODInfo.TONS2011))
IEnumerable myQuery(IEnumerable数据,Func-Func)
{
在数据中从ODInfo返回
其中pLocationIDs.Contains(ODInfo.OID)
按ODInfo.OID将ODInfo分组为g
选择新的输出类型
{
OID=g.键,
总吨=总吨(func)
};
}
var query=myQuery(DataContext.CIMS_TRUCKS,ODInfo=>ODInfo.TONS2009);
K06a的答案很接近,但在服务器端不起作用。试试这个:
IEnumerable<OutputType> myQuery(IEnumerable<InputType> data, Func<InputType,decimal> func)
{
return from ODInfo in data
where pLocationIDs.Contains(ODInfo.OID)
group ODInfo by ODInfo.OID into g
select new OutputType
{
OID = g.Key,
TotalTons = g.Sum(func)
};
}
var query = myQuery(DataContext.CIMS_TRUCKS, ODInfo => ODInfo.TONS2009);
IEnumerable myQuery(IEnumerable数据,表达式expr)
{
从DataContext.CIMS\u中的ODInfo返回
其中pLocationIDs.Contains(ODInfo.OID)
按ODInfo.OID将ODInfo分组为g
选择新的输出类型
{
OID=g.键,
TotalTons=g.AsQueryable().Sum(expr)
};
}
var query=myQuery(DataContext.CIMS_TRUCKS,ODInfo=>ODInfo.TONS2009);
我没有试过,但做过类似的事情
更新
如果您确实需要将输入字符串(如“2009”)转换为表达式,仍然可以:
IEnumerable<OutputType> myQuery(IEnumerable<InputType> data, Expression<Func<InputType,decimal>> expr)
{
return from ODInfo in DataContext.CIMS_TRUCKS
where pLocationIDs.Contains(ODInfo.OID)
group ODInfo by ODInfo.OID into g
select new OutputType
{
OID = g.Key,
TotalTons = g.AsQueryable().Sum(expr)
};
}
var query = myQuery(DataContext.CIMS_TRUCKS, ODInfo => ODInfo.TONS2009);
string year=“2009”;
类型odinfo类型=类型of(odinfo类型);//替换为ODInfo类型
ParameterExpression pe=ParameterExpression.Parameter(ODInfo类型,“ODInfo”);
MemberInfo mi=ODInfoType.GetProperty(“吨”+年);
MemberExpression me=Expression.MakeMemberAccess(pe,mi);
var expr=Expression.Lambda(me,pe);
请注意,这是对数据库中极其恶劣的结构的修补。最好的解决方案是将其分解为多个查询,您可以将其组合成最终查询:
string year = "2009";
Type ODInfoType = typeof(ODINFOTYPE); // substitute with the type of ODInfo
ParameterExpression pe = ParameterExpression.Parameter(ODInfoType, "ODInfo");
MemberInfo mi = ODInfoType.GetProperty("TONS" + year);
MemberExpression me = Expression.MakeMemberAccess(pe, mi);
var expr = Expression.Lambda<Func<ODINFOTYPE, decimal>>(me, pe);
这将在运行时专门处理三个可能的查询,从而提供最佳性能。它比外壳开关更好。使用与EF一起工作的开关:
int year = 2009; // get summ of TONS2009 column
var odInfos =
year == 2009 ? DataContext.CIMS_TRUCKS.Select(x => new { x.OID, TONS = x.TONS2009 })
year == 2010 ? DataContext.CIMS_TRUCKS.Select(x => new { x.OID, TONS = x.TONS2010 })
year == 2011 ? DataContext.CIMS_TRUCKS.Select(x => new { x.OID, TONS = x.TONS2011 })
: null;
var query = from ODInfo in odInfos
where pLocationIDs.Contains(ODInfo.OID)
group ODInfo by ODInfo.OID into g
select new
{
OID = g.Key,
TotalTons = g.Sum(ODInfo => ODInfo.TONS)
};
我不相信表达式或委托可以在EF中以这种方式使用,除非您通过.AsEnumerable()将整个数据带到内存中只是一个问题:您不能在数据模型中对其进行规范化吗?这样的专栏是臭名昭著的反模式。如何规范化?你能再解释一下吗?我有超过22个不同年份的商品数据。22个不同年份x 4种不同模式[卡车、航空、水和铁路]。表太多了。是的,我肯定有很多表和列。至少做一个年份栏和吨栏,并查询其中年份=2009等确定。这就是我要做的。谢谢。这会转换成SQL吗?开关不确定,为什么不工作?如果有什么小毛病,我当然可以修复。@usr我试过了,但没用;我已经编辑了上面的问题。切换不起作用,因为带有语句体的lambda无法转换为表达式。另请参见。不需要任何开关,就像在给出的示例中一样。我仍然必须使用“ODInfo=>ODInfo.TONS2009”对吗?我如何改变这一点?使用表达式类的Cretae表达式?你能举个例子吗?谢谢。作品我必须修复“evid DB”。错误5无法从用法推断方法“System.Linq.Enumerable.Select(System.Collections.Generic.IEnumerable,System.Func)”的类型参数。请尝试显式指定类型参数。C:\Projects\CIMS\FL\u CIMS\Src\FDOTCIMSViewer\FDOTCIMSViewer\WcfServiceTestService\Models\cimsrespository.cs 239 39 FDOTCIMSService
int year = 2009; // get summ of TONS2009 column
var query = from ODInfo in DataContext.CIMS_TRUCKS
where pLocationIDs.Contains(ODInfo.OID)
group ODInfo by ODInfo.OID into g
select g;
var projectedGroups = query.Select("new (Key as OID, Sum(TONS" + year + ") as TotalTons)");