按枚举描述排序我第一次用EF代码写ASP.NETMVC项目,遇到需要按枚举描述排序的情况:publicpartialclassItem{publicenumMyEnumE{[Description("descriptionofenum1")]Enum1,[Description("descriptionofenum2")]Enum2,...}publicMyEnumEMyEnum{get;放;下面是Search和SortAndPaginate函数:varitems=entities.Items.Where(itemFilter);返回等待SortAndPaginate(项目,OrsortName,排序pageNb);}privateasyncTaskSortAndPaginate(IQueryableitems,SortableTypeEsortName,SortOrder.TypeEsortOrder,intpageNb){IOrderedQueryableresult=null;switch(sortName){...caseSortableTypeE.Type:result=sortOrder==SortOrder.TypeE.ASC?items.OrderBy(i=>i.MyEnum.GetDescription()):items.OrderByDescending(i=>i.MyEnum.GetDescription());结果=资源ult.ThenBy(i=>i.SomeOtherProperty);休息;...}if(result!=null){returnawaitresult.ToPagedListAsync(pageNb,10);}返回PagedListHelper.Empty();问题是Item表可能非常庞大我想在ToListAsyncentities.Items.Where(itemFilter)之后立即调用ToListAsync但这将取回所有过滤的项目,尽管我只需要一页。听起来不是个好主意。但是,如果我不这样做,EF将无法理解GetDescription(),我只能想到两个解决方案:-将我的数据库列更改为字符串(枚举描述)而不是枚举本身(但是这听起来像是对我的黑客攻击)-或者直接在枚举声明中按字母顺序排列MyEnumE组件(看起来很脏,MyEnumE也维护)如果我在过滤后立即调用ToListAsync,所有其他解决方案看起来都很脏,我绝对需要从搜索返回的IPagedList方法,所以我担心性能。有没有人知道如何处理这个问题?太感谢了。更新这是GetDescription方法(如有必要可以更改):publicstaticstringGetDescription(thisEnume){FieldInfofi=e.GetType().GetField(e.ToString());DescriptionAttribute[]属性=(DescriptionAttribute[])fi.GetCustomAttributes(typeof(DescriptionAttribute),false);if(attributes.Length>0)返回属性[0].Description;否则返回e.ToString();}解决方案我最终会接受IvanStoev的建议,因为我的项目主要是基于Linq(使用Linq而不是存储过程等),所以这个解决方案似乎比创建参考表更适合我的特定情况。然而,NiyokoYuliawan和MichaelFreidgeim对我来说也是很好的答案,任何阅读本文并有更多数据库方法的人都应该选择他们的解决方案;)非常感谢你们所有人。我将使用动态表达式。它更灵活,可以轻松更改,而不会影响数据库表和查询??。但是,我不是按数据库中的描述字符串排序,而是在内存中创建一个有序映射,将一个int“order”值与每个枚举值相关联,如下所示:publicstaticclassEnumHelper{publicstaticExpression>DescriptionOrder(thisExpression>来源)其中TEnum:struct{varenumType=typeof(TEnum);如果(!enumType.IsEnum)抛出新的InvalidOperationException();varbody=((TEnum[])Enum.GetValues(enumType)).OrderBy(value=>value.GetDescription()).Select((value,ordinal)=>new{value,ordinal}).Reverse()。聚合((表达式)null,(next,item)=>next==null?(Expression)Expression.Constant(item.ordinal):Expression.Condition(Expression.Equal(source.Body,Expression.Constant(item.value))),Expression.Constant(item.ordinal),next));返回Expression.Lambda>(body,source.Parameters[0]);}publicstaticstringGetDescription(这个TEnum值)whereTEnum:struct{varenumType=typeof(TEnum);如果(!enumType.IsEnum)抛出新的InvalidOperationException();varname=Enum.GetName(enumType,value);变量字段=typeof(T枚举).GetField(名称,BindingFlags.Static|BindingFlags.Public);返回字段.GetCustomAttribute()?.Description??姓名;}}用法如下:caseSortableTypeE.Type:varorder=EnumHelper.DescriptionOrder((Itemx)=>x.MyEnum);结果=sortOrder==SortOrder.TypeE.ASC?items.OrderBy(顺序):items.OrderByDescending(顺序);结果=result.ThenBy(i=>i.SomeOtherProperty);休息;这将生成如下表达式:x=>x.MyEnum==Enum[0]?0:x.MyEnum==枚举[1]?1:...x.MyEnum==枚举[N-2]?N-2:N-1;其中0,1,..N-2是按描述排序的值列表中的相应索引备选方案1您可以通过将枚举投影到自定义值并按它排序来实现。例子:items.Select(x=>new{x,Desc=(x.Enum==Enum.One?"DescOne":x.Enum==Enum.Two?"DescTwo"...等等)}).OrderBy(x=>x.Desc).Select(x=>xx);然后,实体框架将生成这样的SQLSELECT*FROMYourTableORDERBYCASEWHENEnum=1THEN'DescOne'WHENEnum=2THEN'DescTwo'...等等END如果你有很多这样的查询,你可以创建扩展方法publicstaticIQueryableOrderByDesc(thisIQueryablesource){returnsource.Select(x=>new{x,Desc=(x.Enum==Enum.One?"DescOne":x.Enum==Enum.Two?"DescTwo"...等等)}).OrderBy(x=>x.Desc).Select(x=>xx);}并在需要时调用它varorderedItems=items.OrderByDesc();替代方案2另一种替代解决方案是创建额外的表,将枚举值映射到枚举描述,并将表连接到该表。该解决方案的性能会更高,因为您可以在枚举描述列上创建索引。备选方案3如果你想要一个基于枚举描述属性的动态表达式,你可以自己构建helper类publicclassHelper{publicMyEntityEntity{get;放;}公共字符串描述{得到;放;}}获取动态构建的表达式publicstaticstringGetDesc(MyEnume){vartype=typeof(MyEnum);varmemInfo=type.GetMember(e.ToString());varattributes=memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute),false);返回((DescriptionAttribute)属性[0])。描述;}privatestaticExpression>GetExpr(){vardescMap=Enum.GetValues(typeof(MyEnum)).Cast().ToDictionary(value=>value,GetDesc);varparamExpr=Expression.Parameter(typeof(MyEntity),"x");varexpr=(Expression)Expression.Constant(string.Empty);foreach(vardescindescMap){//使用实体中的枚举属性名称更改下面的字符串“Enum”varprop=Expression.Property(paramExpr,typeof(MyEntity).GetProperty("Enum"));expr=Expression.Condition(Expression.Equal(prop,Expression.Constant(desc.Key)),Expression.Constant(desc.值),表达式);}varnewExpr=Expression.New(typeof(Helper));varbindings=newMemberBinding[]{Expression.Bind(typeof(Helper).GetProperty("Entity"),paramExpr),Expression.Bind(typeof(Helper).GetProperty("Description"),expr)};varbody=Expression.MemberInit(newExpr,bindings);return(Expression>)Expression.Lambda(body,paramExpr);}像这样调用它vare=GetExpr();items.Select(e).OrderBy(x=>x.Description).Select(x=>x.Entity);将我的数据库列更改为字符串(枚举描述)而不是枚举本身(但对我来说听起来像是hack)相反,对于数据驱动的应用程序,最好在数据库引用表MyItemProperty(MyPropKey,MyPropDescription)并在Items表中包含MyPropKey列。它有一些好处,例如为了保持简单和良好的性能,我会手动订购枚举,你只需要做一次,它会帮助很多publicenumMyEnumE{Enum1=3,Enum2=1,Enum3=2,//在这里设置顺序...}这是一个使用connections的简化示例:以上是C#学习教程:按枚举排序描述所有分享的内容,如果对大家有用还需要详细了解的C#学习教程,希望大家多多关注——usingSystem;使用System.Collections.Generic;使用System.ComponentModel;使用System.Linq;使用System.Reflection;namespaceConsoleApplication{publicpartialclassItem{publicenumMyEnumE{[Description("descriptionofenum1")]Enum1,[Description("descriptionofenum2")]Enum2}publicItem(MyEnumEmyEnum){MyEnum=myEnum;}publicMyEnumEMyEnum{得到;放;}}classProgram{privatestaticIEnumerable>GetEnumRanks(TypeenumType){varvalues=Enum.GetValues(enumType);varresults=newList>(values.Length);foreach(intvalueinvalues){FieldInfofieldInfo=enumType.GetField(Enum.GetName(enumType,value));varattribute=(DescriptionAttribute)fieldInfo.GetCustomAttribute(typeof(DescriptionAttribute));结果.广告d(newKeyValuePair(value,attribute.Description));}returnresults.OrderBy(x=>x.Value).Select((x,i)=>newKeyValuePair(x.Key,i));}staticvoidMain(string[]args){varitemsList=newList();itemsList.Add(新项目(Item.MyEnumE.Enum1));itemsList.Add(新项目(Item.MyEnumE.Enum2));itemsList.Add(新项目(Item.MyEnumE.Enum2));itemsList.Add(新项目(Item.MyEnumE.Enum1));IQueryableitems=itemsList.AsQueryable();vardescriptions=GetEnumRanks(typeof(Item.MyEnumE));//foreach(描述中的vari)//Console.WriteLine(i.Value);varresults=items.Join(descriptions,a=>(int)a.MyEnum,b=>b.Key,(x,y)=>new{Item=x,Rank=y.Value}).OrderBy(x=>x.Rank).Select(x=>x.Item);foreach(variinresults)Console.WriteLine(i.MyEnum.ToString());Console.WriteLine("nPressanykey...");控制台.ReadKey();}}}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如有转载,请注明出处: