DataTable转泛型
前言:在机房基本已经做完的时候,突然发现一个很严重的问题,那就是别人都转泛型了,我怎么没有转呢?当时一下就有点无语了,我做了这么长时间的机房,好不容易要做完了,怎么把这么大的事给忘了呢,看来这回又得继续了。曾经某个同学告诉我说转泛型一点都不难,可简单了,可是昨天写的时候我发现,也没有我想象中的那么简单,虽然说是用一个类就能解决的问题,但我是用c#写的,参考着VB.NET 版的写,也费了了我好大劲呢,但也从中学到不少东西。
什么是泛型:
泛型是程序设计语言的一种特性。允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须作出指明。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。将类型参数化以达到代码复用提高软件开发工作效率的一种数据类型。泛型类是引用类型,是堆对象,主要是引入了类型参数这个概念。在程序编码中一些包含类型参数的类型,也就是说泛型的参数只可以代表类,不能代表个别对象。(这是当今较常见的定义)。
使用泛型的好处:
1.泛型是一种强类型。其处理速度要比普通类快。
2.泛型用来解决创建和使用新的数据类型。泛型也使不同场合的代码重用更加方便。
3.与传统的类相比,泛型更加高效。泛型模板可以提供传统类不能实现的代码重用,在某些情况下可以少些很多代码。
4.与传统类只能使用通用类型(如object)不同,泛型可以指定使用的类型,提供更好的类型保护。
5.性能和类型安全性大大提高。
6. 使用泛型类型可以最大限度地重用代码、保护类型的安全以及提高性能。
代码:
用学生上机记录查询来做例子:
因为在以后会有很多地方用到dataTable转泛型,所以把这个过程写成一个单独的类比较合适,可以写在U层,也可以写在D层。在这里我是写到了D层。
首先是添加两个引用:
using System.Reflection; //一下是添加的引用
using System.Data ;
方法代码:
namespace LoginDAL
{
public class converttoListDAO
{
/// <summary>
/// 单表查询结果转换成泛型集合
/// </summary>
///<param name="T">泛型集合类型</param>
/// <typaram name="dt">查询结果DataTable</param>
/// <returns>以 实体类为元素的泛型集合</returns>
public static List<T> DatatoList<T>(DataTable dt) where T:new ()
{
//定义集合
List<T> mylist = new List<T>();
//获得此模型的类型
Type type=typeof (T);
//定义一个临时变量
string tempName = string.Empty;
//遍历DataTable 中所有的数据行
foreach ( DataRow dr in dt.Rows )
{
T t = new T();
//获得此模型的公共属性
PropertyInfo[] pro = t.GetType().GetProperties ();
//遍历该对象的所有属性
foreach (PropertyInfo pr in pro)
{
tempName = pr.Name;//将属性名称赋值给临时变量
//检查datatable是否包含此列(列名==对象的属性名)
if (dt.Columns .Contains (tempName))
{
//判断此属性是否有setter
if (!pr.CanWrite) continue; //该属性不可写,直接跳出
//q取值:
object value =(dr[tempName.Trim()]);
//int a = Convert.ToInt32(value);
//如果非空,则赋给对象的属性
if(value !=DBNull .Value )
{
pr.SetValue(t,value ,null);
}
}
}
//对象添加到泛型集合中
mylist.Add(t);
}
return mylist;
}
}
}
Facade层代码:
public List<Login.Modle.LineInfo > FaceLine(Login.Modle.LineInfo lineinfo)
{
//Login.BLL.LineBLL linebll = new Login.BLL.LineBLL();
// DataTable lineback1 = new DataTable();
Login.BLL.LineBLL linebll = new Login.BLL.LineBLL();
List<Login.Modle.LineInfo > lineback = new List<Login.Modle.LineInfo >();
lineback = linebll.Linebll (lineinfo); //数据传入到B层中
return lineback;
}
B层代码:
public List<Login.Modle .LineInfo> Linebll(Login.Modle .LineInfo lineinfo)
{
LoginFactory.loginFactory linefactory = new LoginFactory.loginFactory(); //实例化工厂
Login.IDAL.LineIDAL Iline = linefactory.SelectLine(); //实例化接口
// DataTable lineback2 = new DataTable();
List<Login.Modle.LineInfo> lineback2 = new List<Modle.LineInfo>();
lineback2 = Iline.GetLine (lineinfo);
return lineback2;
}
D层代码:
public class lineDAO:Login.IDAL .LineIDAL
{
//public DataTable GetLine(Login.Modle .LineInfo lineinfo)
public List<Login.Modle.LineInfo> GetLine(Login.Modle.LineInfo lineinfo)
{
SqlParameter[] sqlparams={new SqlParameter ("@cardno",lineinfo .CardNo )};
string sql2 = "select * from Line_info where Cardno=@cardno ";
List<Login.Modle.LineInfo> list = new List<Login.Modle.LineInfo>();
DataTable table2 = new DataTable();
table2 = SqlHelper.SqlHelper.GetDataTable(sql2, CommandType.Text ,sqlparams); //调用sqlhelper层
if (table2 .Rows .Count >0)
{
list = LoginDAL.converttoListDAO.DatatoList<Login.Modle.LineInfo>(table2);
}
return list ;
}
}
虽然在写的时候费了很大的劲,但是也从这过程中学到了不少的东西。在转泛型的时候常出的一个错误就是,类型的转换问题,
原因是我们封装的实体中的属性的类型和数据库中相应字段的类型不同。当我们用泛型集合来代替DataTable的时候我们必须保证我们封装的实体的属性名和数据库中字段名一模一样,也就是说我们必须明确要转换的实体类的类型,否则会报错,另外我们在封装实体的属性的类型必须和我们数据库中相应字段的属性一样。
当我们遇到新的不会的知识的时候,不要回避,要大胆尝试着接受,只有这样我们才能学到更多的知识。