c#自定义ORM框架---(泛型&反射&实体类扩展属性<附带通用增、删、查、改>)

时间:2023-03-08 21:33:50

该教材主要是运用到泛型、反射和实体类扩展属性

步骤一、建立扩展属性类

实体类扩展属性要继承Attribute基类完成

 [AttributeUsage(AttributeTargets.Property)]
public class FieldAttribute : Attribute
{
/// <summary>
///是否为主键(true/false)
/// </summary>
public bool PropertyKey { get; set; }
/// <summary>
/// 是否为自动增长(true/false)
/// </summary>
public bool Identity { get; set; }
}
 [AttributeUsage(AttributeTargets.Class)]
public class TableAttribute:Attribute
{
/// <summary>
/// 数据库表名
/// </summary>
public string TableName { get; set; }
}

步骤二、创建实体类并引用扩展实体类属性

注意:
[Serializable]表示实体类可被序列化
[Table(TableName = "emesc.Dome")]表示引入的扩展属性名并且数据库名为emesc.Dome

[Field(PropertyKey = true)]表示是否为主键
 
 [Table(TableName = "emesc.Dome")]
[Serializable]
public class Dome
{
[Field(PropertyKey = true)]
public string EMP_NO { get; set; }
public string EMP_NAME { get; set; }
public string EMP_DESC { get; set; }
public string TYPE { get; set; }
public string EMP_RANK { get; set; }
public string EMP_PASS { get; set; }
public object FACTORY_CODE { get; set; }
public DateTime QUIT_DATE { get; set; }
public object CALENDAR_CODE { get; set; }
}

步骤三、创建BaseClass 该Class主要是用来封装ORM框架的通用方法(增、删、查、改)

  1.反射出实体类所有字段属性

  注意:反射实体类字段主要运用到PropertyInfo[]和泛型T

      PropertyInfo[] 主要反射实体类字段属性

      T 主要是用来传递实体类对象

  

 private static string GetClassType<T>(T modelName) {
try {
StringBuilder type= new StringBuilder();
PropertyInfo[] props = modelName.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);//抓取泛型類的字段屬性;
foreach ( PropertyInfo Info in props) {
//if ((Info.GetValue(modelName,null) + "").Equals("")|| (Info.GetValue(modelName, null) + "").Equals(null)) continue;
//if (Info.PropertyType.Name.StartsWith("DateTime"))
//{
// if (Convert.ToDateTime(Info.GetValue(modelName, null)) == DateTime.MinValue) continue;//判斷時間是否為最小時間 ;
//}
type.Append(Info.Name+",");
}
return type.ToString().Substring(, Start.Length - );//拼接所有字段属性名
}
catch (Exception ex)
{
throw ex;
}
}

  2.反射扩展类字段属性

  /// <summary>
/// 获取实体类中的唯一id和对应的表名
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="modelName"></param>
/// <returns></returns>
public static List<string> GetModelFeature<T>(T modelName) {
try {
List<string> list = new List<string>();
var info= modelName.GetType().GetCustomAttributes(typeof(TableAttribute), false);
foreach (var item in info)
{
TableAttribute attr = item as TableAttribute;
if (attr != null)
{
string tableName = attr.TableName;//表名只有获取一次
list.Add(tableName);
break;
}
}
PropertyInfo[] props = modelName.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);//抓取泛型類的字段屬性;
foreach (var item in props)
{
object[] objAttrs = item.GetCustomAttributes(typeof(FieldAttribute), true);
if (objAttrs.Length > )
{
FieldAttribute attr = objAttrs[] as FieldAttribute;
if (attr.PropertyKey == true)
{
list.Add(item.Name+" = '"+ item.GetValue(modelName,null)+"'");//抓取筛选条件
}
}
}
return list;
}
catch (Exception ex)
{
throw ex;
}
}

  

3. 编写通用增删查改方法 insert、update、delete、Query(select)方法

   通用方法编写思维引导:当我们在对数据库进行操作时我们发现不管怎么对数据库操作都少不了表名、字段名和值 那么我们可以封装函数用来存储字段名和值

   如:insert into 表名 (字段名) values(值)

     update set 字段名=‘值’ from 表名 where 字段名=‘值’

     delete 表名 where 字段名=‘值’

     select 字段名 from 表名 where 字段名=‘值

     存储字段名代码(核心代码):

 private static string GetNumericField<T>(T modelName)
{
try
{
StringBuilder Start = new StringBuilder();
PropertyInfo[] props = modelName.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);//抓取泛型類的字段屬性;
foreach (var item in props)
{
Start.Append(item.Name + ","); }
return Start.ToString().Substring(, Start.Length - );
}
catch (Exception ex)
{
throw ex;
}
}

    存储值代码(核心代码):

 private static string GetValues<T>(T modelName)
{
try {
StringBuilder End = new StringBuilder();
PropertyInfo[] props = modelName.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);//抓取泛型類的字段屬性;
foreach (var item in props)
{
if ((item.GetValue(modelName, null) + "").Equals("") || (item.GetValue(modelName, null) + "").Equals(null)) continue;
if (item.PropertyType.Name.StartsWith("String"))//判斷字段類型
{
End.Append(" and " + item.Name + " = '" + item.GetValue(modelName, null) + "'");
}
else if (item.PropertyType.Name.StartsWith("DateTime"))//判斷字段的屬性是否為時間類型//判斷字段類型
{
if (Convert.ToDateTime(item.GetValue(modelName, null)) == DateTime.MinValue)
{
continue;
}
else
{
End.Append(" and " + item.Name + " = '" + item.GetValue(modelName, null) + "'");
}
}
else
{
End.Append(" and " + item.Name + " = " + item.GetValue(modelName, null) + "");
} }
return End.ToString();
}
catch (Exception ex)
{
throw ex;
}
}

下图为完整版的通用增删改的代码:

  /// <summary>
/// 最低兼容.net 4.0(該ORM緊支持對單表操作)
/// <para>開發時間:2019/5/27</para>
/// <para>開發人員:会害羞的青蛙</para>
/// </summary>
public class BaseFunction
{
DBHelper DB = new DBHelper();
/// <summary>
/// 添加數據(數據錄入時必須將時間轉換為DateTime)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="modelName"></param>
/// <param name="dbName"></param>
/// <returns></returns>
public static int Save<T>(T modelName) {
try {
List<string> list = GetModelFeature(modelName);
string dbName = list[];
StringBuilder SQL = new StringBuilder("insert into ");
StringBuilder End = new StringBuilder();
SQL.Append(dbName + " ("+ GetSaveStart(modelName)+") values ("+ GetSaveEnd(modelName) + ")");
return DBHelper.ExecuteNonQuery(SQL.ToString().Trim().ToUpper());
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 添加數據(數據錄入時必須將時間轉換為DateTime)
/// <para>connectionString為自定義數據庫連接地址支持不同數據庫操作</para>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="modelName"></param>
/// <param name="dbName"></param>
/// <returns></returns>
public static int Save<T>(T modelName,string connectionString)
{
try
{
List<string> list = GetModelFeature(modelName);
string dbName = list[];
StringBuilder SQL = new StringBuilder("insert into ");
StringBuilder End = new StringBuilder();
SQL.Append(dbName + " (" + GetSaveStart(modelName) + ") values (" + GetSaveEnd(modelName) + ")");
return DBHelper.ExecuteNonQuery(SQL.ToString().Trim().ToUpper(), connectionString);
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 根据主键ID修改數據(若没有主键请在实体类定义一个主键,數據編輯時必須將時間轉換為DateTime)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="modelName"></param>
/// <param name="dbName"></param>
/// <returns></returns>
public static int Update<T>(T modelName)
{
try {
List<string> list = GetModelFeature(modelName);
string dbName = list[];//數據庫名
StringBuilder SQL = new StringBuilder("update "+ dbName + " set ");
StringBuilder End = new StringBuilder();
SQL.Append(GetEditStart(modelName) +" where " + list[]);
return DBHelper.ExecuteNonQuery(SQL.ToString().Trim().ToUpper());
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 根据主键ID修改數據(若没有主键请在实体类定义一个主键,數據編輯時必須將時間轉換為DateTime)
/// <para>connectionString為自定義數據庫連接地址支持不同數據庫操作</para>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="modelName"></param>
/// <param name="dbName"></param>
/// <returns></returns>
public static int Update<T>(T modelName, string connectionString)
{
try
{
List<string> list = GetModelFeature(modelName);
string dbName = list[];//數據庫名
StringBuilder SQL = new StringBuilder("update " + dbName + " set ");
StringBuilder End = new StringBuilder();
SQL.Append(GetEditStart(modelName) + " where " + list[]);
return DBHelper.ExecuteNonQuery(SQL.ToString().Trim().ToUpper(), connectionString);
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 根据主键ID删除数据(若没有主键请在实体类定义一个主键)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="modelName"></param>
/// <returns></returns>
public static int Delete<T>(T modelName)
{
try {
List<string> list = GetModelFeature(modelName);
string dbName = list[];//數據庫名
string primaryKey = string.Empty;
string primaryValue = string.Empty;
PropertyInfo[] props = modelName.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);//抓取泛型類的字段屬性;
foreach (var item in props)
{
object[] objAttrs = item.GetCustomAttributes(typeof(FieldAttribute), true);
if (objAttrs.Length > )
{
FieldAttribute attr = objAttrs[] as FieldAttribute;
if (attr.PropertyKey == true)
{
primaryKey = item.Name;
primaryValue = item.GetValue(modelName, null)+"";
}
}
}
if (primaryValue=="") { throw new Exception("主键不能为空!"); }
StringBuilder SQL = new StringBuilder("delete " + dbName+ " where " + primaryKey+"='"+ primaryValue + "'");
return DBHelper.ExecuteNonQuery(SQL.ToString().Trim().ToUpper());
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 根据主键ID删除数据(若没有主键请在实体类定义一个主键)
/// <para>connectionString為自定義數據庫連接地址支持不同數據庫操作</para>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="modelName"></param>
/// <returns></returns>
public static int Delete<T>(T modelName, string connectionString)
{
try
{
List<string> list = GetModelFeature(modelName);
string dbName = list[];//數據庫名
string primaryKey = string.Empty;
string primaryValue = string.Empty;
PropertyInfo[] props = modelName.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);//抓取泛型類的字段屬性;
foreach (var item in props)
{
object[] objAttrs = item.GetCustomAttributes(typeof(FieldAttribute), true);
if (objAttrs.Length > )
{
FieldAttribute attr = objAttrs[] as FieldAttribute;
if (attr.PropertyKey == true)
{
primaryKey = item.Name;
primaryValue = item.GetValue(modelName, null) + "";
}
}
}
if (primaryValue == "") { throw new Exception("主键不能为空!"); }
StringBuilder SQL = new StringBuilder("delete " + dbName + " where " + primaryKey + "='" + primaryValue + "'");
return DBHelper.ExecuteNonQuery(SQL.ToString().Trim().ToUpper(), connectionString);
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 查询所有结果 modelName(实体类)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="modelName"></param>
/// <returns></returns>
public static DataTable QueryList<T>(T modelName) {
try {
List<string> list = GetModelFeature(modelName);
string dbName = list[];//數據庫名
StringBuilder Start = new StringBuilder();
Start.Append(GetQueryStart(modelName));
StringBuilder End = new StringBuilder();
End.Append(GetQueryEnd(modelName));
string SQL = "SELECT " + Start + " FROM " + dbName + " WHERE 1=1" + End;
return DBHelper.GetMultipleResults(SQL.ToString().Trim().ToUpper());
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 查询所有结果 modelName(实体类)
/// <para>connectionString為自定義數據庫連接地址支持不同數據庫操作</para>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="modelName"></param>
/// <returns></returns>
public static DataTable QueryList<T>(T modelName, string connectionString)
{
try
{
List<string> list = GetModelFeature(modelName);
string dbName = list[];//數據庫名
StringBuilder Start = new StringBuilder();
Start.Append(GetQueryStart(modelName));
StringBuilder End = new StringBuilder();
End.Append(GetQueryEnd(modelName));
string SQL = "SELECT " + Start + " FROM " + dbName + " WHERE 1=1" + End;
return DBHelper.GetMultipleResults(SQL.ToString().Trim().ToUpper(), connectionString);
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 查询所有结果(包含分页)modelName(实体类),page(当前页),linmt(当前页的总条数),count(结果集总条数)
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="modelName"></param>
/// <param name="page"></param>
/// <param name="linmt"></param>
/// <returns></returns>
public static DataTable QueryList<T>(T modelName, int page, int linmt ,out int count)
{
try {
List<string> list = GetModelFeature(modelName);
string dbName = list[];//數據庫名
StringBuilder Start = new StringBuilder();
Start.Append(GetQueryStart(modelName));
StringBuilder StartToPagination = new StringBuilder();
StartToPagination.Append(GetQueryStartToPagination(modelName));
StringBuilder End = new StringBuilder();
End.Append(GetQueryEnd(modelName)); count = Convert.ToInt32(DBHelper.GetMultipleResults("SELECT COUNT(*) AS COUNTNUM FROM " + dbName+" WHERE 1=1 "+ End).Rows[]["COUNTNUM"]);
string SQL = "SELECT " + StartToPagination + " FROM (SELECT ROWNUM AS NUM ," + Start + " FROM " + dbName + " WHERE 1=1" + End + " AND ROWNUM<=" + linmt + "*" + page + ") WHERE NUM>" + linmt + "*(" + page + "-1) ";
return DBHelper.GetMultipleResults(SQL.ToString().Trim().ToUpper());
}
catch (Exception ex) {
throw ex;
}
}
/// <summary>
/// 查询所有结果(包含分页)modelName(实体类),page(当前页),linmt(当前页的总条数),count(结果集总条数)
/// <para>connectionString為自定義數據庫連接地址支持不同數據庫操作</para>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="modelName"></param>
/// <param name="page"></param>
/// <param name="linmt"></param>
/// <returns></returns>
public static DataTable QueryList<T>(T modelName, string connectionString, int page, int linmt, out int count)
{
try
{
List<string> list = GetModelFeature(modelName);
string dbName = list[];//數據庫名
StringBuilder Start = new StringBuilder();
Start.Append(GetQueryStart(modelName));
StringBuilder StartToPagination = new StringBuilder();
StartToPagination.Append(GetQueryStartToPagination(modelName));
StringBuilder End = new StringBuilder();
End.Append(GetQueryEnd(modelName)); count = Convert.ToInt32(DBHelper.GetMultipleResults("SELECT COUNT(*) AS COUNTNUM FROM " + dbName + " WHERE 1=1 " + End).Rows[]["COUNTNUM"]);
string SQL = "SELECT " + StartToPagination + " FROM (SELECT ROWNUM AS NUM ," + Start + " FROM " + dbName + " WHERE 1=1" + End + " AND ROWNUM<=" + linmt + "*" + page + ") WHERE NUM>" + linmt + "*(" + page + "-1) ";
return DBHelper.GetMultipleResults(SQL.ToString().Trim().ToUpper(), connectionString);
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 获取实体类中的唯一id和对应的表名
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="modelName"></param>
/// <returns></returns>
public static List<string> GetModelFeature<T>(T modelName) {
try {
List<string> list = new List<string>();
var info= modelName.GetType().GetCustomAttributes(typeof(TableAttribute), false);
foreach (var item in info)
{
TableAttribute attr = item as TableAttribute;
if (attr != null)
{
string tableName = attr.TableName;//表名只有获取一次
list.Add(tableName);
break;
}
}
PropertyInfo[] props = modelName.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);//抓取泛型類的字段屬性;
foreach (var item in props)
{
object[] objAttrs = item.GetCustomAttributes(typeof(FieldAttribute), true);
if (objAttrs.Length > )
{
FieldAttribute attr = objAttrs[] as FieldAttribute;
if (attr.PropertyKey == true)
{
list.Add(item.Name+" = '"+ item.GetValue(modelName,null)+"'");//抓取筛选条件
}
}
}
return list;
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 獲取起始字段
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="modelName"></param>
/// <returns></returns>
private static string GetSaveStart<T>(T modelName) {
try {
StringBuilder Start = new StringBuilder();
PropertyInfo[] props = modelName.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);//抓取泛型類的字段屬性;
foreach ( PropertyInfo Info in props) {
if ((Info.GetValue(modelName,null) + "").Equals("")|| (Info.GetValue(modelName, null) + "").Equals(null)) continue;
if (Info.PropertyType.Name.StartsWith("DateTime"))
{
if (Convert.ToDateTime(Info.GetValue(modelName, null)) == DateTime.MinValue) continue;//判斷時間是否為最小時間 ;
}
Start.Append(Info.Name+",");
}
return Start.ToString().Substring(, Start.Length - );
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 獲取字段對應的結果
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="modelName"></param>
/// <returns></returns>
private static string GetSaveEnd<T>(T modelName)
{
try {
StringBuilder End = new StringBuilder();
PropertyInfo[] props = modelName.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);//抓取泛型類的字段屬性;
foreach (PropertyInfo Info in props)
{
if ((Info.GetValue(modelName, null) + "").Equals("") || (Info.GetValue(modelName, null) + "").Equals(null)) continue; if (Info.PropertyType.Name.StartsWith("String"))//判斷字段類型
{
End.Append("'" + Info.GetValue(modelName, null) + "',");
}
else if (Info.PropertyType.Name.StartsWith("DateTime"))//判斷字段類型
{
if (Convert.ToDateTime(Info.GetValue(modelName, null)) == DateTime.MinValue)//判斷時間是否為最小時間
{
continue;
}
else {
End.Append("to_date('" + ((DateTime)(Info.GetValue(modelName, null))).ToString("yyyy-MM-dd HH:mm:ss") + "','YYYY-MM-DD HH24:MI:SS'),");
}
}
else {
End.Append(Info.GetValue(modelName, null) + ",");
}
}
return End.ToString().Substring(, End.Length - );
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 重新定義分頁後的查詢字段並且格式化DateTime樣式
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="modelName"></param>
/// <returns></returns>
private static string GetQueryStartToPagination<T>(T modelName) {
try {
StringBuilder Start = new StringBuilder();
PropertyInfo[] props = modelName.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);//抓取泛型類的字段屬性;
foreach (var item in props)
{
if (item.PropertyType.Name.StartsWith("DateTime"))//判斷字段的屬性是否為時間類型
{
Start.Append("TO_CHAR(" + item.Name + ",'YYYY-MM-DD HH:mm:ss') AS " + item.Name + ",");//格式化時間
}
else {
Start.Append(item.Name + ",");
} }
return Start.ToString().Substring(, Start.Length - );
}
catch (Exception ex)
{
throw ex;
}
}
private static string GetQueryStart<T>(T modelName)
{
try
{
StringBuilder Start = new StringBuilder();
PropertyInfo[] props = modelName.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);//抓取泛型類的字段屬性;
foreach (var item in props)
{
Start.Append(item.Name + ","); }
return Start.ToString().Substring(, Start.Length - );
}
catch (Exception ex)
{
throw ex;
}
}
private static string GetQueryEnd<T>(T modelName)
{
try {
StringBuilder End = new StringBuilder();
PropertyInfo[] props = modelName.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);//抓取泛型類的字段屬性;
foreach (var item in props)
{
if ((item.GetValue(modelName, null) + "").Equals("") || (item.GetValue(modelName, null) + "").Equals(null)) continue;
if (item.PropertyType.Name.StartsWith("String"))//判斷字段類型
{
End.Append(" and " + item.Name + " = '" + item.GetValue(modelName, null) + "'");
}
else if (item.PropertyType.Name.StartsWith("DateTime"))//判斷字段的屬性是否為時間類型//判斷字段類型
{
if (Convert.ToDateTime(item.GetValue(modelName, null)) == DateTime.MinValue)
{
continue;
}
else
{
End.Append(" and " + item.Name + " = '" + item.GetValue(modelName, null) + "'");
}
}
else
{
End.Append(" and " + item.Name + " = " + item.GetValue(modelName, null) + "");
} }
return End.ToString();
}
catch (Exception ex)
{
throw ex;
}
}
/// <summary>
/// 编辑起始内容
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="modelName"></param>
/// <returns></returns>
private static string GetEditStart<T>(T modelName) {
try {
StringBuilder Start = new StringBuilder();
PropertyInfo[] props = modelName.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);//抓取泛型類的字段屬性;
foreach (PropertyInfo Info in props)
{
object[] objAttrs = Info.GetCustomAttributes(typeof(FieldAttribute), true);
if (objAttrs.Length > )
{
FieldAttribute attr = objAttrs[] as FieldAttribute;
if (attr.PropertyKey == true) continue;//判断自定义特性中的主键
}
if ((Info.GetValue(modelName, null) + "").Equals("") || (Info.GetValue(modelName, null) + "").Equals(null)) continue; if (Info.PropertyType.Name.StartsWith("String"))//判斷字段類型
{
Start.Append(Info.Name + "='" + Info.GetValue(modelName, null) + "',");
}
else if (Info.PropertyType.Name.StartsWith("DateTime"))//判斷字段類型
{
if (Convert.ToDateTime(Info.GetValue(modelName, null)) == DateTime.MinValue)//判斷時間是否為最小時間
{
continue;
}
else
{
Start.Append(Info.Name+"=to_date('" + ((DateTime)(Info.GetValue(modelName, null))).ToString("yyyy-MM-dd HH:mm:ss") + "','YYYY-MM-DD HH24:MI:SS'),");
}
}
else {
Start.Append(Info.Name + "=" + Info.GetValue(modelName, null) + ",");
}
}
return Start.ToString().Substring(, Start.Length - );
}
catch (Exception ex)
{
throw ex;
}
}
}

 

  警告:严禁以商用名义贩卖此代码

  代码紧提供学习使用,若要转载此教程备注原创者:会害羞的青蛙