2016-09-03 60 views
1

对于我的应用程序,我想根据当前的Item类型,通过静态字典值对我的Item实体进行排序。 不管我怎么努力我不能让它工作,始终得到一个错误说:按静态字典值对linq查询进行排序

无法创建类型的常量值“System.Collections.Generic.KeyValuePair`2 [MyApp.Models。 Item + ItemTypeE,MyApp,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null],[System.Int32,mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089]]。只有原始类型或枚举类型在此背景下

这里支持我的版本库的方法试图将Item实体排序:

private IOrderedQueryable<Item> Sort(IQueryable<Item> items) 
{ 
    return items.OrderBy(i => i.Type) 
       .ThenBy(i => 
        Item.MyDic.Keys.Any(key => key == i.Type) 
        ? Item.MyDic[i.Type].Item2 
        : -1); 
} 

而且Item类:

public partial class Item : CavalenaEntity, ICavalenaEntity 
{ 
    public enum ItemTypeE 
    { 
     Type1 = 0, 
     Type2 = 1, 
     ... 
    } 

    public static Dictionary<ItemTypeE, Tuple<int, int>> MyDic = new Dictionary<ItemTypeE, Tuple<int, int>>() 
    { 
     { ItemTypeE.Type1, new Tuple<int, int>(0, 1) }, 
     { ItemTypeE.Type2, new Tuple<int, int>(1, 100) }, 
     ... 
    } 
} 

Item.MyDic.Keys.Any(key => key == i.Type)是工作正常,但我无法找到一种方式来实现像Item.MyDic[i.Type].Item2。 我试过选择KeyValuePair成一个新的匿名对象,也尝试使用selectMany,但我仍然无法使它工作。

如果任何人都可以告诉我一种实现这样的查询的方式,我会非常感激。 非常感谢。

最终解决

public IPagedList<Item> GetSoldableItems(Item.SortableTypeE sortName, SortOrder.TypeE sortOrder, int pageNb) 
    { 
     var items = entities.Items.Where(i => ...); 

     var orderedItems = Sort(items.AsEnumerable(), sortName, sortOrder).ToList(); 

     return orderedItems.ToPagedList(pageNb, 10); 
    } 

    private IOrderedEnumerable<Item> Sort(IEnumerable<Item> items, Item.SortableTypeE sortName, SortOrder.TypeE sortOrder) 
    { 
     IOrderedEnumerable<Item> result = null; 

     switch(sortName) 
     { 
      case Item.SortableTypeE.Type: 
       result = sortOrder == SortOrder.TypeE.ASC 
        ? items.OrderBy(i => i.Type) 
        : items.OrderByDescending(i => i.Type); 
       result = result.ThenBy(i => 
         Item.MyDisc.ContainsKey(i.Type) 
         ? Item.MyDisc[i.Type].Item2 
         : -1) 
        .ThenByDescending(i => i.Bonus); 
       break; 
      ... 
      default: break; 
     } 

     return result; 
    } 

回答

1

的问题是,供应商正在试图翻译查询转换成SQL,它未能这样做,因为您使用的是本地内存辞典你的排序逻辑。解决方案是拖动数据并将其排序在内存中。由于没有过滤这里,这应该是从性能方面罚款:

private IEnumerable<Item> Sort(IQueryable<Item> items) 
{ 
    return items.AsEnumerable().OrderBy(i => i.Type) 
           .ThenBy(i => Item.MyDic.Keys.Any(key => key == i.Type) 
              ? Item.MyDic[i.Type].Item2: -1); 
} 

其他情况注:避免使用AsEnumerable()时,有后过滤逻辑,因为这样你就不会被过滤的服务器端。

+0

感谢您的回答!然而,整个事情实际上是相当大的,以参数,排序和排序顺序为标准。我发布的'sort'方法实际上是在过滤之后调用的,并且取决于排序列和顺序。我简化了这篇文章,因为我认为这不是很重要,因为这个问题只是为了获得字典价值。另外,'Item'表可能有很多行。使用'AsEnumerable()'还可以吗?有没有其他方法? –

+1

@Flash_Back由于您之前正在过滤,因此没有可以注意到的性能影响。至于其他方式,那么不行!您无法在SQL翻译的Linq查询中使用本地字典。想想看,这个查询需要被转换成纯SQL,当你有一个带有自定义类型和元组的本地键值对字典时,提供者怎么做呢?如果您确实需要在服务器端执行所有操作,那么编写一个存储过程并使用Linq调用它,然后将结果映射到对象中。但这超出了这个答案的范围。 – user3185569

+0

我其实对演出很害怕,但是你所说的话肯定会让人感觉到,因为过滤完成之前不应该有任何问题。非常感谢您的解释我现在更了解它;) –