然后在选择后失败

时间:2011-11-04 09:22:30

标签: .net linq linq-to-sql iqueryable

我正在尝试通过另一个表中的某个值(通过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传递给函数。

2 个答案:

答案 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

订购