博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
.net 开发框架(二) [实体层与ScriptQuery类]
阅读量:6253 次
发布时间:2019-06-22

本文共 10488 字,大约阅读时间需要 34 分钟。

     本篇我描述DevNet中实体层的实现,.net的数据集很强大,原来做cs项目时都用的DataTable,不管从性能,灵活性,可操作性以及写代码的方便性都很实用,唯一感觉不舒服的是在获取某字段值是需要使用DataRow[fieldName]或者DataRow[index]方式,在项目需求变化数据字段有变化时,需要修改大量的字段名称,在编译时并不会报错,项目很容易出错。再到后来做bs项目时使用了实体模式,虽然在灵活性及List数据集的计算等方面不如DataTable方便,但感觉在维护及开发调试中方便了许多。

  实体如果都要手写的话就受不了了,网上很多生成实体的工具,我也根据DevNet类库弄了个实体生成器,有需要的朋友可以到第一篇下载。

      在转换成实体时原先都是用反射方法,网上绝大部分都使用该方法,虽然用起来没啥大问题,但我感觉对性能多少有点影响。下面的反射转换实体的代码,DevNet类库中仍保留着。

  

代码
///
<summary>
///
获取实体集合[使用反射]
///
</summary>
///
<typeparam name="T">
实体(请确保存在无参数构造函数)
</typeparam>
///
<param name="table">
内存表
</param>
///
<returns></returns>
public
static
List
<
T
>
GetEntityCollection
<
T
>
(DataTable table)
where
T :
class
,
new
()
{
if
(table
==
null
)
throw
new
ArgumentNullException(
"
table
"
,
"
参数table不能为null
"
);
List
<
T
>
ts
=
new
List
<
T
>
();
foreach
(DataRow dr
in
table.Rows)
{
T t
=
new
T();
SetObjByRow(t, dr);
ts.Add(t);
}
return
ts;
}
///
<summary>
///
从DataRow中获取数据设置Object对象[实体类]的值[使用反射]
///
</summary>
///
<typeparam name="T"></typeparam>
///
<param name="objEntity">
Object对象[实体类](属性名称请与数据表字段名称保持一致)
</param>
///
<param name="dataRow"></param>
///
<returns></returns>
public
static
void
SetObjByRow
<
T
>
(T objEntity, DataRow dataRow)
where
T :
class
{
if
(objEntity
==
null
)
throw
new
ArgumentNullException(
"
objEntity
"
);
if
(dataRow
==
null
)
throw
new
ArgumentNullException(
"
dataRow
"
);
System.Reflection.PropertyInfo[] objs
=
objEntity.GetType().GetProperties();
foreach
(System.Reflection.PropertyInfo pobj
in
objs)
{
int
i
=
dataRow.Table.Columns.IndexOf(pobj.Name);
if
(i
>=
0
)
{
if
(dataRow[pobj.Name]
is
DBNull)
continue
;
try
{
pobj.SetValue(objEntity, dataRow[pobj.Name],
null
);
}
catch
(Exception ex)
{
throw
new
Exception(
"
设置实体属性
"
+
pobj.Name
+
"
值时出错,请检查数据表字段
"
+
pobj.Name
+
"
和该实体属性类型是否一致。
"
+
ex.Message, ex);
}
}
}
}

 

 

 

  这些方法都在DevNet的DBHelper.cs类中 ,该类中也保留了从DbDataReader转换成实体集合的方法。你可以从(一)篇文档中下载的DevNet.chm文件中查找。

  本来一直使用也相安无事,本着精益求精的精神,一直想把反射的方法改掉,所幸从网上找到了方法,有位似乎叫深蓝博士(很抱歉,记得不太清了,如果您看到此篇还请见谅)的博客中实体的思路,方法相当不错,根据他的实体模式,我修改了我的实体结构,从我的实体生成器中选择EntityBase项生成的实体如下:

 

代码
using
System;
using
System.Collections.Generic;
using
System.Text;
using
DevNet.Common;
//
请添加引用
using
DevNet.Common.Entity;
namespace
CodeDemo.Entity
{
#region
====PermissionEntity====
///
<summary>
///
表 Permission 的实体类
///
</summary>
[Serializable]
public
class
Permission: EntityBase
{
public
Permission()
{
AddProperty(PermissionID_FieldName,
0
);
AddProperty(PermissionName_FieldName,
string
.Empty);
AddProperty(PermissionMemo_FieldName,
string
.Empty);
AddProperty(PerParentID_FieldName,
0
);
AddProperty(ImageURL_FieldName,
string
.Empty);
AddProperty(LinkURL_FieldName,
string
.Empty);
AddProperty(DisplayIndex_FieldName,
0
);
AddProperty(IsShow_FieldName,
false
);
AddProperty(Owner_FieldName,
0
);
base
.TableName
=
Permission_TableName;
base
.AutoIncrements
=
AutoIncrement;
base
.PrimaryKeyFields
=
PrimaryKeyField;
}
#region
====表名称、字段名称、主键字段、自动增长型字段名称====
///
<summary>
///
表 Permission 数据表名称
///
</summary>
public
const
string
Permission_TableName
=
"
PERMISSION
"
;
///
<summary>
///
表 Permission 主键字段集合
///
</summary>
public
readonly
static
string
[] PrimaryKeyField
=
new
string
[] {
"
PermissionID
"
};
///
<summary>
///
表 Permission 自动增长型字段名称
///
</summary>
public
const
string
AutoIncrement
=
""
;
///
<summary>
///
PermissionID 字段名称
///
</summary>
public
const
string
PermissionID_FieldName
=
"
PermissionID
"
;
///
<summary>
///
权限名称 字段名称
///
</summary>
public
const
string
PermissionName_FieldName
=
"
PermissionName
"
;
///
<summary>
///
权限说明 字段名称
///
</summary>
public
const
string
PermissionMemo_FieldName
=
"
PermissionMemo
"
;
///
<summary>
///
父权限ID 字段名称
///
</summary>
public
const
string
PerParentID_FieldName
=
"
PerParentID
"
;
///
<summary>
///
图片URL 字段名称
///
</summary>
public
const
string
ImageURL_FieldName
=
"
ImageURL
"
;
///
<summary>
///
连接URL 字段名称
///
</summary>
public
const
string
LinkURL_FieldName
=
"
LinkURL
"
;
///
<summary>
///
显示索引 字段名称
///
</summary>
public
const
string
DisplayIndex_FieldName
=
"
DisplayIndex
"
;
///
<summary>
///
是否在管理显示 字段名称
///
</summary>
public
const
string
IsShow_FieldName
=
"
IsShow
"
;
///
<summary>
///
权限所属后台系统(多后台系统,譬如:1系统后台权限 2用户后台权限 3园区后台权限 4 政府后台权限......) 字段名称
///
</summary>
public
const
string
Owner_FieldName
=
"
Owner
"
;
#endregion
#region
====字段属性====
///
<summary>
///
PermissionID 列
///
</summary>
public
int
PermissionID
{
get
{
return
Convert.ToInt32(GetProperty(PermissionID_FieldName));
}
set
{
SetProperty(PermissionID_FieldName, value);
}
}
///
<summary>
///
权限名称 列
///
</summary>
public
string
PermissionName
{
get
{
return
Convert.ToString(GetProperty(PermissionName_FieldName));
}
set
{
SetProperty(PermissionName_FieldName, value);
}
}
///
<summary>
///
权限说明 列
///
</summary>
public
string
PermissionMemo
{
get
{
return
Convert.ToString(GetProperty(PermissionMemo_FieldName));
}
set
{
SetProperty(PermissionMemo_FieldName, value);
}
}
///
<summary>
///
父权限ID 列
///
</summary>
public
int
PerParentID
{
get
{
return
Convert.ToInt32(GetProperty(PerParentID_FieldName));
}
set
{
SetProperty(PerParentID_FieldName, value);
}
}
///
<summary>
///
图片URL 列
///
</summary>
public
string
ImageURL
{
get
{
return
Convert.ToString(GetProperty(ImageURL_FieldName));
}
set
{
SetProperty(ImageURL_FieldName, value);
}
}
///
<summary>
///
连接URL 列
///
</summary>
public
string
LinkURL
{
get
{
return
Convert.ToString(GetProperty(LinkURL_FieldName));
}
set
{
SetProperty(LinkURL_FieldName, value);
}
}
///
<summary>
///
显示索引 列
///
</summary>
public
int
DisplayIndex
{
get
{
return
Convert.ToInt32(GetProperty(DisplayIndex_FieldName));
}
set
{
SetProperty(DisplayIndex_FieldName, value);
}
}
///
<summary>
///
是否在管理显示 列
///
</summary>
public
bool
IsShow
{
get
{
return
Convert.ToBoolean(GetProperty(IsShow_FieldName));
}
set
{
SetProperty(IsShow_FieldName, value);
}
}
///
<summary>
///
权限所属后台系统(多后台系统,譬如:1系统后台权限 2用户后台权限 3园区后台权限 4 政府后台权限......) 列
///
</summary>
public
int
Owner
{
get
{
return
Convert.ToInt32(GetProperty(Owner_FieldName));
}
set
{
SetProperty(Owner_FieldName, value);
}
}
#endregion
#region
====表关系属性====
#endregion
}
#endregion
}

  实体中的常量是数据表的字段名称,我配合使用我的ScriptQuery.cs类(下面会讲一点)操作,完全不需要把字段名称写在项目中,有了这个实体,那么实体转换就不再需要用反射了。

 

代码
///
<summary>
///
设置实体属性值[使用EntityBase中的方法]
///
</summary>
///
<typeparam name="T">
实体泛型[请继承自EntityBase]
</typeparam>
///
<param name="objEntity">
泛型对象[请继承自EntityBase](属性名称请与数据表字段名称保持一致)
</param>
///
<param name="dataRow">
DataRow数据行
</param>
public
static
void
SetEntityByRow
<
T
>
(T objEntity, DataRow dataRow)
where
T : EntityBase
{
if
(objEntity
==
null
)
throw
new
ArgumentNullException(
"
objEntity
"
);
if
(dataRow
==
null
)
throw
new
ArgumentNullException(
"
dataRow
"
);
foreach
(DataColumn col
in
dataRow.Table.Columns)
{
if
(dataRow[col]
is
DBNull)
continue
;
objEntity.SetPropertyValue(col.ColumnName, dataRow[col]);
}
}

在DBHelper.cs类中你可以找到该方法。使用实体的SetPropertyValue方法设置实体属性值,不再依赖反射。另外在该类中有这样一个方法

 

代码
///
<summary>
///
根据Object对象[实体类]设置DbParameter参数值[使用反射]
///
</summary>
///
<typeparam name="T"></typeparam>
///
<param name="objEntity">
Object对象[实体类](属性名称请与参数名称保持一致)
</param>
///
<param name="parameter"></param>
public
static
void
SetParamsValue
<
T
>
(T objEntity,
params
DbParameter[] parameter)
where
T :
class
{
if
(parameter
==
null
)
throw
new
ArgumentNullException(
"
parameter
"
);
if
(objEntity
!=
null
)
{
System.Reflection.PropertyInfo[] properties
=
objEntity.GetType().GetProperties();
foreach
(DbParameter p
in
parameter)
{
if
(p.Direction
==
ParameterDirection.ReturnValue)
//
ParameterName == flag + "RETURN_VALUE")
{
continue
;
}
foreach
(System.Reflection.PropertyInfo property
in
properties)
{
if
(property.Name.Equals(p.ParameterName.Substring(
1
),StringComparison.OrdinalIgnoreCase))
{
try
{
p.Value
=
property.GetValue(objEntity,
null
);
}
catch
(Exception ex)
{
throw
new
Exception(
"
设置参数
"
+
p.ParameterName
+
"
值时出错,请检查实体属性名
"
+
property.Name
+
"
和该参数类型是否一致。
"
+
ex.Message, ex);
}
if
(p.Value
==
null
)
{
throw
new
ArgumentException(
"
实体属性名:
"
+
property.Name
+
"
值为 null,请提供该属性值
"
,
property.Name);
}
break
;
}
}
}
}
}

该方法的实体类是指参数查询实体类,不知道各位在多条件查询时如何做的,本人使用查询实体类来作为查询条件传递的。该方法是使用反射方法,根据查询实体属性名称来设置DbParameter的参数值。我想各位都看过微软的SqlHelper类,该类中有方法可以从存储过程中直接创建参数并放入缓存,在DevNet类库中DBStoredParams.cs类中包含了此类方法并且修改成使用Dbparameter抽象类,不再局限于Sql存储过程参数(虽然很多都用的sql存储过程)。

  实体的结构就是以上这些,下面描述一下ScriptQuery.cs。

  该类基于第一篇DBConnect数据库连接对象,使用参数模式简单的封装了一些sql语句以及提供了简单的操作帮助,代码在此就不贴了,贴些部分使用代码

 

代码
ScriptQuery _query
=
new
ScriptQuery(
"
tb_user
"
);
_query.Select().ALL().From().Where(Tb_user.Userid_FieldName,
5
, ScriptQuery.CompareEnum.MoreThan).AddOrderBy()
.OrderBy(Tb_user.Userid_FieldName, ScriptQuery.SortEnum.DESC);
_query.PageIndex
=
1
;
_query.PageSize
=
10
;
List
<
Tb_user
>
users
=
_query.GetList
<
Tb_user
>
();
MessageBox.Show(
"
RecordCount:
"
+
_query.RecordCount.ToString()
+
"
PageCount:
"
+
_query.PageCount.ToString());

该方法获取分页信息列表,默认使用sql2005分页语句(ROW_NUMBER() OVER (ORDER BY {0}),配置文件appSettings节中

 <add key="IsSql2000" value="true"/>

将使用top语句查询分页,在使用top语句分页查询时请设置PrimaryKey查询主键的属性值(默认名称为“id”),否则将出错。

再看一下该类如何使用存储过程

 

代码
//
存储过程
         Tb_user user = _query.GetSingle<Tb_user>(Tb_user.Userid_FieldName, id, ScriptQuery.CompareEnum.Equal);
DbParameter[] ps
=
DBStoredParams.GetSpParameter(
"
sp_tb_user_insertupdate
"
);
DBHelper.SetParamsInfo(user, ps);
//
这里设置不使用反射,提高效率 user为数据表对应的实体
_query.Value
=
"
sp_tb_user_insertupdate
"
;
_query.SetCmdParameters(ps);
_query.CmdType
=
CommandType.StoredProcedure;
_query.ExecuteNonQuery();

 

下面是查询实体参数的使用: 

代码
//基类抽象方法的实现
public
override
List
<
NewBooks
>
GetPageList(SearchNewBooks condition, Pagination pagination,
string
sortFieldName,
ScriptQuery.SortEnum sortEnum)
{
Script.Select().ALL().From().Where();
if
(
!
string
.IsNullOrEmpty(condition.F_Sm))
{
Script.Like(NewBooks.F_SM_FieldName, condition.F_Sm);
}
if
(
!
string
.IsNullOrEmpty(condition.F_BBMC))
{
Script.Like(NewBooks.F_BBMC_FieldName, condition.F_BBMC);
}
if
(condition.IsShow
!=
2
)
{
Script.Where(NewBooks.IsShow_FieldName, condition.IsShow);
}
Script.Between(NewBooks.F_DJ_FieldName, condition.MinPrice, condition.MaxPrice);
Script.Between(NewBooks.AddDate_FieldName, condition.StartDate, condition.EndDate);
Script.AddOrderBy().OrderBy(sortFieldName, sortEnum);
Script.PageIndex
=
pagination.PageIndex;
Script.PageSize
=
pagination.PageSize;
List
<
NewBooks
>
lists
=
Script.GetList
<
NewBooks
>
();
pagination.RecordCount
=
Script.RecordCount;
return
lists;
}

 实体层与ScriptQuery就到此,下一篇描述DevNet的DAL数据层。

转载于:https://www.cnblogs.com/sjfe_cn/archive/2010/11/08/Entity.html

你可能感兴趣的文章
hcg值小于0.1_【原理】JavaScript 中 0.1 + 0.2 为什么不等于 0.3?
查看>>
springboot的jsp应该放在哪_健身小白用2个月亲身经历告诉你小白去健身房,应该做到哪几点...
查看>>
opencv表面缺陷检测_工业产品表面缺陷检测方法
查看>>
kettle使用数据库来生成序列_时间序列数据库Influxdb的使用
查看>>
配置babel_关于 Babel 你必须知道的
查看>>
数据丢失与重复_消息队列重复消费和数据丢失问题(石衫面试突击学习笔记)...
查看>>
摄像头 火狐_为什么谷歌浏览器打不开电脑摄像头?
查看>>
两张图片合成一张_ps技巧:大光比照片后期曝光合成技法
查看>>
码条形码属性_条码生成器如何批量生成code 11码
查看>>
和lua的效率对比测试_不同编程语言能耗不同?看这27种语言对比!
查看>>
让某控件失去焦点_常用基本控件测试用例(一)
查看>>
天气模式_今年台风活跃期即将结束!下周天气将开启“大变脸”模式
查看>>
扫码枪关闭常亮模式_生意好时最怕收银出故障,这几个扫码枪的常见问题你一定要知道...
查看>>
如何双击打开vivado工程_利用TCL重建vivado工程
查看>>
mysql的引双向链表_Mysql高手系列 - 第22篇:mysql索引原理详解(高手必备技能)
查看>>
mysql in 查询改成_MySQL not in嵌套查询改写成外连接方式
查看>>
mysql community安装_MySQL Community Server 5.7安装详细步骤
查看>>
python处理多行字符串_python多行字符串
查看>>
java冒泡排序_用java写个冒泡排序?
查看>>
linux 开发java_做开发环境的操作系统是 Linux 好还是 Windows 好?
查看>>