当前位置: 首页 > 编程语言 > C#

在C#中将DataTable转换为通用列表分享

时间:2023-04-10 17:23:43 C#

C#学习教程:在C#中将DataTable转换为泛型列表我的查询有点不同。编码语言:C#3.5我有一个名为cardsTable的DataTable从数据库中提取数据,我有一个类Cards,它只有一些属性(没有构造函数)publicclassCards{publicInt64CardID{get;放;}publicstring}publicInt64ProjectID{get;放;}publicDoubleCardWidth{get;放;}publicDoubleCardHeight{get;放;}publicstringOrientation{get;放;}publicstringBackgroundImage{get;放;}公共字符串背景{得到;放;我想将cardsTable数据插入到List类型的对象中。我的数据将包含空字段,因此当我转换数据时该方法不应出错。以下方法是最好的方法吗?数据表dt=GetDataFromDB();列表目标=dt.AsEnumerable().ToList().ConvertAll(x=>newCards{CardID=(Int64)x.ItemArray[0]});你实际上可以大大缩短它。您可以将Select()扩展方法视为类型转换器。然后可以将转换写为:Listtarget=dt.AsEnumerable().Select(row=>newCards{//假设第0列的类型为NullableCardID=row.Field(0).GetValueOrDefault(),CardName=String。IsNullOrEmpty(row.Field(1))?“未找到”:row.Field(1),}).ToList();我认为如果您使用一些约定和反射,您可以改进所有解决方案并使该方法更通用。假设您将数据表中的列命名为与对象中的属性相同的名称,那么您可以编写一些查看对象所有属性的内容,然后查找数据表中的列以映射该值。我是反着做的,就是...从IList到datatable,我写的代码可以从另一边看http://blog.tomasjansson.com/convert-datatable-to-generic-list-extension/它应该不难说,而且应该很难重载该函数,以便您可以提供有关包含或排除哪些属性的信息。编辑:所以让它工作的代码是:publicstaticclassDataTableExtensions{privatestaticDictionarytypeDictionary=newDictionary>();publicstaticIListGetPropertiesForType(){vartype=typeof(T);if(!typeDictionary.ContainsKey(typeof(T))){typeDictionary.Add(type,type.GetProperties().ToList());}返回类型字典[类型];}publicstaticIListToList(thisDataTabletable)whereT:new(){IListproperties=GetPropertiesForType();IListresult=newList();foreach(varrowintable.Rows){varitem=CreateItemFromRow((DataRow)row,properties);结果。添加(项目);}返回结果;}privatestaticTCreateItemFromRow(DataRowrow,IListproperties)whereT:new(){Titem=newT();foreach(属性中的var属性){属性。SetValue(item,row[property.Name],null);}归还物品;如果你有一个数据表,你可以只写yourTable.ToList(),它会为你创建列表。如果您的嵌套对象具有更复杂的类型,则需要更新您的代码。一个建议是重载ToList方法以接受包含所有不应映射的属性的paramsstring[]excludeProperties。当然,您可以在CreateItemForRow方法的foreach循环中添加一些空值检查。更新:添加一个静态字典来存储反射操作的结果使其更快一些。我没有编译代码,但它应该可以工作:)。.ToList()放错地方了,有些字段能为null就必须处理,因为如果为null就不会转换成Int64DataTabledt=GetDataFromDB();列表目标=dt.AsEnumerable()。Select(x=>newCards{CardID=(Int64)(x.ItemArray[0]??0)}).ToList();只是一点点简化。我不使用ItemArray:Listlist=tbl.AsEnumerable().Select(x=>newPerson{Id=(Int32)(x["Id"]),Name=(string)(x["Name"]??""),LastName=(string)(x["LastName"]??"")}).ToList();及其单行解决方案这取决于您知道数据库中的数据都是有效的并且不包含任何会破坏上述内容的内容,例如当您没有想到它时可以为null的字段-可能是由于左连接数据生成数据。所以,如果您之前验证过数据,那么-我很乐意建议一些linq-但你已经失败了。如果您需要一些验证,您应该只遍历数据行,生成上述对象并将其添加到集合中......这也将允许您处理一行中的错误并仍然处理其余部分。无论如何,这就是我的看法(该死的我接下来投票了,所以我的代表是1024)您可以使用如下所示的通用类将数据表映射到模型类。通用类publicstaticclassDataTableMappingtoModel{//////将数据表值映射到对应的模型属性////////////publicstaticListMappingToEntity(thisDataTabledt){try{varlst=newList();vartClass=typeof(T);PropertyInfo[]proInModel=tClass.GetProperties();列出proInDataColumns=dt.Columns.Cast().ToList();Tcn;foreach(dt.Rows中的数据行项){cn=(T)Activator.CreateInstance(tClass);foreach(varpcinproInModel){vard=proInDataColumns.Find(c=>string.Equals(c.ColumnName.ToLower().Trim(),pc.Name.ToLower().Trim(),StringComparison.CurrentCultureIgnoreCase));if(d!=null)pc.SetValue(cn,item[pc.Name],null);}lst.Add(cn);}返回列表;}catch(Exceptione){抛出e;}}}模特课publicclassItem{publicstringItemCode{get;放;}publicstringCost{得到;放;}publicoverridestringToString(){return"ItemCode:"+ItemCode+",Cost:"+Cost;}}创建DataTablepublicDataTablegetTable(){DataTabledt=newDataTable();dt.Columns.Add(newDataColumn("ItemCode",typeof(string)));dt.Columns.Add(newDataColumn("Cost",typeof(string)));数据行博士;for(inti=0;i现在我们可以将此DataTable转换为List,如下所示:DataTabledt=getTable();Listlst=dt.ToCollection();foreach(Itemcninlst){Response.Write(cn.ToString()+"");}希望这有助于我建立在TomasJansson的逻辑上并包含一个“忽略”属性这使我可以在不破坏DataTable-To-Class加载本身的情况下将其他属性添加到正在加载的类中。或者,我还会考虑添加一个单独的参数来保存要在DataTable中读取的实际列名。在这种情况下,不要使用“row[property.Name]”,而是使用row[attribute.Name]”或类似的.公共静态类DataTableExtensions{[AttributeUsage(AttributeTargets.Property,Inherited=false,AllowMultiple=true)]publicsealedclassIgnoreAttribute:Attribute{publicIgnoreAttribute(){}}privatestaticDictionarytypeDictionary=newDictionary>();publicstaticIListGetPropertiesForType(){vartype=typeof(T);如果(!typeDictionary.ContainsKey(typeof(T)))typeDictionary.Add(type,type.GetProperties().ToList());返回类型字典[类型];}publicstaticIListToList(thisDataTabletable)whereT:new(){IListproperties=GetPropertiesForType();IListresult=newList();foreach(varrowintable.Rows)result.Add(CreateItemFromRow((DataRow)row,properties));返回结果;}privatestaticTCreateItemFromRow(DataRowrow,IListproperties)whereT:new(){Titem=newT();foreach(varpropertyinproperties){//只加载那些没有用忽略属性标记的属性varatr=property.GetCustomAttribute(类型(忽略属性));如果(atr==null)property.SetValue(item,row[property.Name],null);}归还物品;}}晚了但是这可能有用可以使用:table.Map();或者使用Func调用来过滤值。您甚至可以通过在其上设置属性来更改类型属性和DataColumn标头之间映射的名称。[AttributeUsage(AttributeTargets.Property)]publicclassSimppleMapperAttribute:Attribute{publicstringHeaderName{get;放;}}publicstaticclassSimpleMapper{#regionpropertiespublicstaticboolUseDeferredExecution{get;放;}=真;#endregion#regionpublic_interfacepublicstaticIEnumerableMapWhere(thisDataTabletable,FuncsortExpression)whereT:new(){varresult=table.Select().Select(row=>ConvertRow(row,table.Columns,typeof(T).GetProperties())).Where((t)=>sortExpression(t));返回UseDeferredExecution?结果:result.ToArray();}publicstaticIEnumerableMap(thisDataTabletable)whereT:new(){varresult=table.Select().Select(row=>ConvertRow(row,table.Columns,typeof(T).GetProperties()));返回UseDeferredExecution?结果:result.ToArray();}#endregion#regionimplementation_detailsprivatestaticTConvertRow(DataRowrow,DataColumnCollectioncolumns,System.Reflection.PropertyInfo[]p_info)whereT:new(){varinstance=newT();foreach(varinfoinp_info){if(columns.Contains(GetMappingName(info)))SetProperty(row,instance,info);}返回实例;}privatestaticvoidSetProperty(DataRowrow,Tinstance,System.Reflection.PropertyInfoinfo)whereT:new(){stringmp_name=GetMappingName(info);对象值=行[mp_name];info.SetValue(实例,值);}privatestaticstringGetMappingName(System.Reflection.PropertyInfoinfo){SimpleMapperAttributeattribute=info.GetCustomAttributes(typeof(SimpleMapperAttribute),true).Select((o)=>oasSimpleMapperAttribute).FirstOrDefault();info.Name:attribute.HeaderName;这是使用Where条件Listfilter=ds.Tables[0].AsEnumerable().Where(x=>x.Field("FilterID")==在c#中转换为通用列表的简单方法5).Select(row=>newFilter{FilterID=row.Field("FilterID"),FilterName=row.Field("FilterName")}).ToList();首先定义属性并使用publicclassFilter{publiccintFilterID{得到;放;}publicstringFilterName{get;需要了解更多C#学习教程,希望大家多多关注---usingSystem.Linq;使用System.Collections.Generic;转载请注明出处: