DataTable填充实体类返回泛型集合

2024-05-08 19:58

本文主要是介绍DataTable填充实体类返回泛型集合,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 昨天找坤哥看到我的一段代码,如下:


     

     稍微解释下,这段代码时D层查询结束后,将datatable查询到的结果赋值给实体对象的属性,然后返回实体的过程,坤哥看了之后问我,如果实体有500多个属性,难道也要这样一条一条的写吗?如果返回多个实体时怎么办?这时,我才意识到自己的代码时非常有问题的,原来设计的是每个方法最多返回一个实体,但是当遇到查询到多条记录的时候,就又冒着破坏三层结构的事返回Datatable去了,真的是很有问题啊。


     怎么改,我脑海中一下子就浮现了老办法:数组+循环,用循环读条读取列值,保存到对象数组。之后查了查,发现我太OUT了。明明就有又新又好的技术可我用过了也想不起来。


    百度上是用的是这样的:在实体层添加一个工具类,类似D层的工具类,只不过这个工具类是完成将datatable转换为一个包含实体的泛型集合的,然后每次返回的时候,将集合作为结果返回。


     这个方法最好的地方还是在对每个实体属性的赋值上面,通过内部的属性集合循环赋值,再也不用一条条写了,这样,不仅封装性好了,而且使代码更不容易出错。

     

      但是,唯一遗憾的就是,使用这个工具类对于实体和datatable有一个条件限制,就是实体的属性名必须和datatable的列名对应。


      在百度上找了很多这样的类,但是只找到了C#版的,然后自己改写了个VB.NET版的。下面写出自己的DEMO:


      首先,是实体类:

      这个实体类是对教师信息表的映射。

     

[vb]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Public Class EntityUser  
  2.   
  3.   
  4.     Private FilUserName As String  '用户名  
  5.     Private FilPwd As String   '密码  
  6.     Private FilTeaName As String   '教师姓名  
  7.     Private FilTeaLevel As String  '教师级别  
  8.     Private FilRegDate As String '注册日期  
  9.     Private FilRegTime As String   '注册时间  
  10.     Private FilDelDate As String   '注销日期  
  11.     Private FilDelTime As String   '注销时间  
  12.     Private FilOnLineStatue As String  '在线状态  
  13.   
  14.   
  15.     ''' <summary>  
  16.     ''' 用户名  
  17.     ''' </summary>  
  18.     ''' <value></value>  
  19.     ''' <returns></returns>  
  20.     ''' <remarks></remarks>  
  21.     Public Property UserName() As String  
  22.         Get  
  23.             Return FilUserName  
  24.         End Get  
  25.         Set(ByVal value As String)  
  26.             FilUserName = value  
  27.         End Set  
  28.     End Property  
  29.   
  30.     ''' <summary>  
  31.     ''' 密码  
  32.     ''' </summary>  
  33.     ''' <value></value>  
  34.     ''' <returns></returns>  
  35.     ''' <remarks></remarks>  
  36.     Public Property Pwd() As String  
  37.         Get  
  38.             Return FilPwd  
  39.         End Get  
  40.         Set(ByVal value As String)  
  41.             FilPwd = value  
  42.         End Set  
  43.     End Property  
  44.   
  45.     ''' <summary>  
  46.     ''' 教师姓名  
  47.     ''' </summary>  
  48.     ''' <value></value>  
  49.     ''' <returns></returns>  
  50.     ''' <remarks></remarks>  
  51.     Public Property TeaName() As String  
  52.         Get  
  53.             Return FilTeaName  
  54.         End Get  
  55.         Set(ByVal value As String)  
  56.             FilTeaName = value  
  57.         End Set  
  58.     End Property  
  59.   
  60.     ''' <summary>  
  61.     ''' 教师级别  
  62.     ''' </summary>  
  63.     ''' <value></value>  
  64.     ''' <returns></returns>  
  65.     ''' <remarks></remarks>  
  66.     Public Property TeaLevel() As String  
  67.         Get  
  68.             Return FilTeaLevel  
  69.         End Get  
  70.         Set(ByVal value As String)  
  71.             FilTeaLevel = value  
  72.         End Set  
  73.     End Property  
  74.   
  75.     ''' <summary>  
  76.     ''' 注册日期  
  77.     ''' </summary>  
  78.     ''' <value></value>  
  79.     ''' <returns></returns>  
  80.     ''' <remarks></remarks>  
  81.     Public Property RegDate() As String  
  82.         Get  
  83.             Return FilRegDate  
  84.         End Get  
  85.         Set(ByVal value As String)  
  86.             FilRegDate = value  
  87.         End Set  
  88.     End Property  
  89.     ''' <summary>  
  90.     ''' 注册时间  
  91.     ''' </summary>  
  92.     ''' <value></value>  
  93.     ''' <returns></returns>  
  94.     ''' <remarks></remarks>  
  95.     Public Property RegTime() As String  
  96.         Get  
  97.             Return FilDelDate  
  98.         End Get  
  99.         Set(ByVal value As String)  
  100.             FilDelTime = value  
  101.         End Set  
  102.     End Property  
  103.     ''' <summary>  
  104.     ''' 注销日期  
  105.     ''' </summary>  
  106.     ''' <value></value>  
  107.     ''' <returns></returns>  
  108.     ''' <remarks></remarks>  
  109.     Public Property DelDate() As String  
  110.         Get  
  111.             Return FilDelDate  
  112.         End Get  
  113.         Set(ByVal value As String)  
  114.             FilDelDate = value  
  115.         End Set  
  116.     End Property  
  117.   
  118.     ''' <summary>  
  119.     ''' 注销时间  
  120.     ''' </summary>  
  121.     ''' <value></value>  
  122.     ''' <returns></returns>  
  123.     ''' <remarks></remarks>  
  124.     Public Property DelTime() As String  
  125.         Get  
  126.             Return FilDelTime  
  127.         End Get  
  128.         Set(ByVal value As String)  
  129.             FilDelTime = value  
  130.         End Set  
  131.     End Property  
  132.   
  133.     ''' <summary>  
  134.     ''' 在线状态  
  135.     ''' </summary>  
  136.     ''' <value></value>  
  137.     ''' <returns></returns>  
  138.     ''' <remarks></remarks>  
  139.     Public Property OnLineStatue() As String  
  140.         Get  
  141.             Return FilOnLineStatue  
  142.         End Get  
  143.         Set(ByVal value As String)  
  144.             FilOnLineStatue = value  
  145.         End Set  
  146.     End Property  
  147.   
  148. End Class  

    

  我 的教师信息表如下:里面有3条记录,这个结果等一会咱们运行的时候会用到。


     

      

    然后,写了个SqlHelper,这个代码不再写。因为这里是做个DEMO,所以没有采用3层架构,大家做的时候要注意不要破坏整体的结构

  
        然后下面就是本文主要要讨论的EntityHelper,不知道这样取名准不准确,但是如果要把这个类加入三层里面,我会把向SQLHelper那样对待,将它作为实体层的一个工具类加进去。

     

[vb]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. Imports System.Collections.Generic  '增加泛型的命名空间  
  2. Imports System.Reflection '引入反射:为了使用PropertyInfo  
  3.   
  4. Public Class EntityHelper  
  5.   
  6.     Public Shared Function convertToList(Of T As {New})(ByVal dt As DataTable) As IList(Of T)  '将datatable转化为泛型集合  
  7.         '注意:1,convertToList(Of T As {New}) 这里的new是用来约束T的,必须有,不然new T的时候会出现错误  
  8.         '2,new约束在C#和VB.NET里面的写法是不一样的,C#里面用的是where来为T加上约束的  
  9.   
  10.         Dim myList As New List(Of T)   '定义最终返回的集合  
  11.   
  12.         Dim myTpye As Type = GetType(T) '得到实体类的类型名  
  13.         Dim dr As DataRow   '定义行集  
  14.   
  15.         Dim tempName As String = String.Empty   '定义一个临时变量  
  16.   
  17.         '遍历DataTable的所有数据行  
  18.         For Each dr In dt.Rows  
  19.   
  20.             Dim myT As New T    '定义一个实体类的对象  
  21.             Dim propertys() As PropertyInfo = myT.GetType().GetProperties()  '定义属性集合  
  22.             Dim Pr As PropertyInfo  
  23.   
  24.             '遍历该对象的所有属性  
  25.             For Each Pr In propertys  
  26.                 tempName = Pr.Name '将属性名称赋值给临时变量  
  27.   
  28.                 '检查DataTable是否包含此列(列名==对象的属性名)   
  29.                 If (dt.Columns.Contains(tempName)) Then     '将此属性与datatable里的列明比较,查看datatable是否包含此属性  
  30.   
  31.                     '判断此属性是否有Setter  
  32.                     If (Pr.CanWrite = FalseThen   '判断此属性是否可写,如果不可写,跳出本次循环  
  33.                         Continue For  
  34.                     End If  
  35.   
  36.                     Dim value As Object = dr(tempName)  '定义一个对象型的变量来保存列的值  
  37.   
  38.                     If (value.ToString <> DBNull.Value.ToString()) Then '如果非空,则赋给对象的属性  
  39.                         Pr.SetValue(myT, value, Nothing)    '在运行期间,通过反射,动态的访问一个对象的属性  
  40.                     End If  
  41.                 End If  
  42.             Next  
  43.   
  44.             myList.Add(myT)   '添加到集合  
  45.         Next  
  46.   
  47.         Return myList   '返回实体集合  
  48.     End Function  
  49.   
  50.   
  51.   
  52. End Class  


   至此,主要的类都写完了,下面来看下客户端该如何调用:


    

[vb]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1.   <span style="font-size:18px;">      Dim strSQL As String = "select * from T_TeaInfo where TeaLevel ='管理员'"  '注意,这种破坏架构的写法不提倡  
  2.   
  3.         Dim mysqlhelper As New SQLHelper '定义查询助手类  
  4.         Dim dt As New DataTable '定义查询到的表集  
  5.   
  6.         Dim myList As List(Of EntityUser)  '保存转换后的泛型集合  
  7.   
  8.         dt = mysqlhelper.ExecSelect(strSQL, CommandType.Text)   '执行查询  
  9.   
  10.         '将dt转换为泛型集合  
  11.         myList = EntityHelper.convertToList(Of EntityUser)(dt)  
  12.   
  13.         TextBox1.Text = myList.Count    '在文本框里面显示出查询到的教师数目  
  14. </span>  


运行后,可以看到,结果如下:


       

   

   小结下:

         对于三层中,可能刚开始做的时候,我们从D层向上层传数据的时候用的是Datatable,只能说,这是一种非常破坏结构的方法,自己真的体会到了实体的好处,才会用它。



绑定控件显示

在D层查询完成之后,我们将DataTable转化为泛型集合,然后经过中间各层,返回U层,到了这里,问题来了,我们这时候要将这个集合作为数据源绑定到DataGridView上,并将结果显示出来,本文主要介绍的就是如何将集合显示在DataGridView上的问题。(或许你返回的是datatable或一个实体,它们加载数据的原理是一至滴~)


      一,显示实体的全部属性

            当DataGridView的列名就是Class T的属性的时候,这时,只需要绑定数据源,然后手动更改列名就好。


[vb]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:14px;"'将dt转换为泛型集合  
  2.   myList = EntityHelper.convertToList(Of EntityUser)(dt)  
  3.   
  4.   TextBox1.Text = myList.Count    '在文本框里面显示出查询到的教师数目  
  5.   
  6.   If (myList.Count > 0) Then      '如果查询到记录  
  7.       ''''将查询到的数据显示到DataGridView中  
  8.       myDataGrid.DataSource = myList  '设置控件的数据源:但是这样设置还不够,因为列的名字显示出来还是英文的,所以,还应该设置没列的名字。  
  9.   
  10.       '修改列名  
  11.       myDataGrid.Columns(0).HeaderText = "卡号"  
  12.       myDataGrid.Columns(1).HeaderText = "密码"  
  13.       myDataGrid.Columns(2).HeaderText = "教师姓名"  
  14.       myDataGrid.Columns(3).HeaderText = "教师级别"  
  15.       myDataGrid.Columns(4).HeaderText = "注册日期"  
  16.       myDataGrid.Columns(5).HeaderText = "注册时间"  
  17.       myDataGrid.Columns(6).HeaderText = "注销日期"  
  18.       myDataGrid.Columns(7).HeaderText = "注销时间"  
  19.       myDataGrid.Columns(8).HeaderText = "上机状态"  
  20.   
  21.   Else  
  22.       MsgBox("没有查询到任何记录!")  
  23.   End If</span>  



显示结果如下:


 



  二,显示Class T 的部分属性

                   有时候,我们并不是要显示T 的全部属性,只需要显示一部分,比如,我们在显示教师信息的时候,可能不需要显示教师的密码,这时候该怎么办呢?


           方法一:加载完所有数据后手动移除列

                    如上图中,如果我想移除密码这一列,只需在加载完所有数据后,再加上一句代码:

         

[vb]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. '加载完所有数据后手动移除密码这一列  
  2. myDataGrid.Columns.Remove("Pwd")  

                当再次显示,结果就如下图:



          

              虽然也能实现想要的效果,但是总感觉这么做有点儿雷,就好像吃了东西再吐出来那样,反正我是不用。还是看看别的方法吧。


              方法二:设置DataPropertyName属性

                         例如,我现在只想显示用户名,首先,右击窗体上的DataGridView控件,然后选择编辑列:



添加一个叫用户名的列,然后设置列的DataPropertyName属性,通过这个属性,可以设置绑定到实体的某个属性值,datatable的某个列等。  这里的DataPropertyName值要跟实体的属性名对应



           之后,我们在代码里面写入

[vb]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:18px;">       myDataGrid.AutoGenerateColumns = False  '不允许自动添加列  
  2.       myDataGrid.DataSource = myList '设置数据源</span>  

             这样就ok了~


        运行下,可以看到这种效果:


        

         小结:

                   真心感觉DataGridView这个空间非常好用,直接绑定数据源就可以显示数据。

           而且如果在D层,查询完成之后,就将datatable转化为实体集,当结果传到U层DataGridView显示的时候,直接指定dataSource为实体集合,那么,整个过程没有像以前vb中MSHFlexGrid控件那样:

              

           



        这个过程每次都要一行一行的赋值,避免了filds属性在指定时出错的问题,而且代码更简洁了,我们的工作量也大大减少了。


这篇关于DataTable填充实体类返回泛型集合的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/971293

相关文章

pandas中位数填充空值的实现示例

《pandas中位数填充空值的实现示例》中位数填充是一种简单而有效的方法,用于填充数据集中缺失的值,本文就来介绍一下pandas中位数填充空值的实现,具有一定的参考价值,感兴趣的可以了解一下... 目录什么是中位数填充?为什么选择中位数填充?示例数据结果分析完整代码总结在数据分析和机器学习过程中,处理缺失数

使用Pandas进行均值填充的实现

《使用Pandas进行均值填充的实现》缺失数据(NaN值)是一个常见的问题,我们可以通过多种方法来处理缺失数据,其中一种常用的方法是均值填充,本文主要介绍了使用Pandas进行均值填充的实现,感兴趣的... 目录什么是均值填充?为什么选择均值填充?均值填充的步骤实际代码示例总结在数据分析和处理过程中,缺失数

C# Where 泛型约束的实现

《C#Where泛型约束的实现》本文主要介绍了C#Where泛型约束的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录使用的对象约束分类where T : structwhere T : classwhere T : ne

Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案

《Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案》:本文主要介绍Vue3组件中getCurrentInstance()获取App实例,但是返回nu... 目录vue3组件中getCurrentInstajavascriptnce()获取App实例,但是返回n

前端下载文件时如何后端返回的文件流一些常见方法

《前端下载文件时如何后端返回的文件流一些常见方法》:本文主要介绍前端下载文件时如何后端返回的文件流一些常见方法,包括使用Blob和URL.createObjectURL创建下载链接,以及处理带有C... 目录1. 使用 Blob 和 URL.createObjectURL 创建下载链接例子:使用 Blob

Python获取C++中返回的char*字段的两种思路

《Python获取C++中返回的char*字段的两种思路》有时候需要获取C++函数中返回来的不定长的char*字符串,本文小编为大家找到了两种解决问题的思路,感兴趣的小伙伴可以跟随小编一起学习一下... 有时候需要获取C++函数中返回来的不定长的char*字符串,目前我找到两种解决问题的思路,具体实现如下:

使用Sentinel自定义返回和实现区分来源方式

《使用Sentinel自定义返回和实现区分来源方式》:本文主要介绍使用Sentinel自定义返回和实现区分来源方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Sentinel自定义返回和实现区分来源1. 自定义错误返回2. 实现区分来源总结Sentinel自定

基于Spring实现自定义错误信息返回详解

《基于Spring实现自定义错误信息返回详解》这篇文章主要为大家详细介绍了如何基于Spring实现自定义错误信息返回效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录背景目标实现产出背景Spring 提供了 @RestConChina编程trollerAdvice 用来实现 HTT

Python容器类型之列表/字典/元组/集合方式

《Python容器类型之列表/字典/元组/集合方式》:本文主要介绍Python容器类型之列表/字典/元组/集合方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1. 列表(List) - 有序可变序列1.1 基本特性1.2 核心操作1.3 应用场景2. 字典(D

SpringBoot自定义注解如何解决公共字段填充问题

《SpringBoot自定义注解如何解决公共字段填充问题》本文介绍了在系统开发中,如何使用AOP切面编程实现公共字段自动填充的功能,从而简化代码,通过自定义注解和切面类,可以统一处理创建时间和修改时间... 目录1.1 问题分析1.2 实现思路1.3 代码开发1.3.1 步骤一1.3.2 步骤二1.3.3