我正在尝试通过另一个表中的某个值(通过Join)对我的主表(Contract)进行排序,然后将其再次缩减为Contracts并按合同中的值对其进行排序(ThenBy)。
这是我的问题的简短版本:
是否可以将复合匿名类型(由Join生成)减少为已定义的类型,而无需将IOrderedQueryable转换为IQueryable?
例子的长版本问题:
我的生产代码非常复杂但是出于这个问题的目的,我把它简化为一个简单的例子:
static void simple()
{
bool condition = true;
var ctx = new LxDataContext();
IQueryable<Contract> q1 = ctx.Contracts.Join(ctx.ContractDetails, c => c.ContractId, cd => cd.ContractId, (c, cd) => new { c, cd }).
Where(J => J.cd.DetailNo > 0).
Select(J => J.c);
IOrderedQueryable<Contract> qOrdered;
if (condition)
{
qOrdered = (IOrderedQueryable<Contract>)q1.Join(ctx.ContractPartners, c => c.ContractId, cp => cp.ContractId, (c, cp) => new { c, cp }).
Join(ctx.VwPartners, J => J.cp.PartnerId, p => p.PartnerId, (J, p) => new { J.c, p }).
OrderBy(J => J.p.LastName).
Select(J => J.c);
}
else
qOrdered = q1.OrderBy(c => c.Premium);
IOrderedQueryable<Contract> qReady = (qOrdered).ThenBy(c => c.ContractId); //if condition == true exception here
var dump = qReady.Skip(50).Take(50).ToList();
}
当条件为假时,一切都有效。 但是,当执行更复杂的OrderBy()时,ThenBy()会因此异常而失败:
Expression of type 'System.Linq.IQueryable`1[InfoServiceTests.DB.Contract]' cannot be used for parameter of type 'System.Linq.IOrderedQueryable`1[InfoServiceTests.DB.Contract]' of method 'System.Linq.IOrderedQueryable`1[InfoServiceTests.DB.Contract] ThenBy[Contract,Int32](System.Linq.IOrderedQueryable`1[InfoServiceTests.DB.Contract], System.Linq.Expressions.Expression`1[System.Func`2[InfoServiceTests.DB.Contract,System.Int32]])'
所以即使我把它转换为IOrderedQueryable&lt;&gt; qOrdered似乎不是IOrderedQueryable&lt;&gt;而ThenBy()失败了。是否可以按另一个表中的某些内容进行排序,然后将结果减少到Contract,然后再次对它进行排序?
一些评论:
- 如果对您有任何帮助:在我的生产代码中,我有一个通用的排序类,主要取自this answer。
- 是的我知道这个例子很容易修复,但在我的生产代码中,我需要一个通用的解决方案来按用户定义的值进行排序。这会调用循环并将Queryables传递给函数。
答案 0 :(得分:0)
当条件为OK时,您应该在选择查询后不添加一些排序因为查询不是有序查询而ThenBy只是在有序查询后才有效:
对序列中的元素进行后续排序 升序。
例如,在你的真实情况下你可以做(在你的if条件下):
qOrdered = (IOrderedQueryable<Contract>)q1
.Join(ctx.ContractPartners,
c => c.ContractId, cp => cp.ContractId, (c, cp) => new { c, cp }).
Join(ctx.VwPartners, J => J.cp.PartnerId,
p => p.PartnerId, (J, p) => new { J.c, p }).
OrderBy(J => J.p.LastName).ThenBy(J=>J.ContractId)
Select(J => J.c);
你可以(在你的声明中):
qOrdered = q1.OrderBy(c => c.Premium).ThenBy(c=>c.ContractId);
此外,您应该在if语句后删除当前的ThenBy操作。
事实上你应该找到可以订购的东西和OrderBy,然后使用ThenBy。
答案 1 :(得分:0)
将if中的代码更改为:
qOrdered = (IOrderedQueryable<Contract>)q1.Join(ctx.ContractPartners, c => c.ContractId, cp => cp.ContractId, (c, cp) => new { c, cp }).
Join(ctx.VwPartners, J => J.cp.PartnerId, p => p.PartnerId, (J, p) => new { J.c, p }).
Select(J => J.c).
OrderBy(J => J.p.LastName)
这将返回一个IOrderedQueryable。如果选择是添加结束,您将获得一个正常的IQueryable,无法使用ThenBy
订购