本文手把手實作一個簡單的ORM架構,僅作為學習,免去多餘的功能,力求簡單。本文使用VS2022,資料庫是MS SQL Server。
一、 什麼是ORM?
ORM即對象關系映射,英文叫:Object-Relational Mapping。它的作用是在将關系型資料庫中的資料表和業務實體類之間作一個映射。ORM使得我們隻需操作對象的方法和屬性,即可完成對資料庫的增删查改,避免了與複雜繁瑣的SQL語句打交道。
ORM隐藏了通路資料庫的細節,使得新手可以簡單地操作資料庫,但同時有些好學的技術人員希望了解ORM到底是怎麼實作的。
二、ORM實作原理
我們都知道,操作資料庫需要編寫SQL語句,SQL語句有增删查改事務存儲過程等。SQL語句都有固定的要求格式,而語句中的字段則是根據資料表字段的不同而不同。
(1)定義一個類,此類的屬性與資料表的字段一一對應。
(2)利用C#中的反射,獲得類的字段名稱,類名等資訊。
(3)當要向資料庫新增資料時,将字段名、類名組裝成SQL語句,再連接配接資料庫進行執行,其他删除、查詢、修改的操作也類似。
三、準備工作-建立資料表scheduleList
本執行個體使用VS2022,基于NET6,microsoft SQL Server 2012。建立一資料庫,名稱随意,并建立一資料表,名稱scheduleList。有三個字段ID、title、和createTime,分别表示是主鍵ID,标題和建立時間。
四、定義scheduleList類
定義一個類,名為scheduleList。代碼如下:
/**
*scheduleList.cs
*
*Ver 變更日期 作者
*V1.0 2022-03-28 12:33:21
*
*VX:lwdred QQ:463183376
*/
using System;
namespace Model.schedule
{
/// <summary>
///
/// </summary>
//[Serializable]
[EntityHelper.Model.Property("scheduleList")]
public class scheduleList
{
private long _id=0;
/// <summary>
/// ID
/// </summary>
[EntityHelper.Model.Property(EntityHelper.Model.ColumnKeyType.Identity)]
public long id
{
set{ _id=value;}
get{return _id;}
}
private string _title=string.Empty;
/// <summary>
/// 标題
/// </summary>
public string title
{
set{ _title=value;}
get{return _title;}
}
private DateTime _createtime=DateTime.Now;
/// <summary>
/// 建立時間
/// </summary>
public DateTime createTime
{
set{ _createtime=value;}
get{return _createtime;}
}
}
}
類scheduleList,有三個字段ID、title、和createTime,分别含義是主鍵ID,标題和建立時間。為簡單起見,本ORM并沒有作别名設計,是以注意三個字段名與資料庫表中的字段需一摸一樣。
其中以下語句是用來标記該字段ID作為主鍵。
[EntityHelper.Model.Property(EntityHelper.Model.ColumnKeyType.Identity)]
以下語句用來标記目前類對應的資料表名是:scheduleList。
[EntityHelper.Model.Property("scheduleList")]
五、通過反射從類資訊中獲得字段名稱和資料表名稱
//定義實體
scheduleList schedule = new scheduleList();
schedule.id= 1;
schedule.title = "标題";
schedule.createTime = DateTime.Now;
使用C#中的反射(System.Reflection),從實體中獲得字段清單,将字段一一填充至SQL語句中,SQL語句就組裝好了。
//通過反射獲得實體字段
Type type = typeof(scheduleList);
PropertyInfo[] pis = type.GetProperties();
foreach (PropertyInfo pi in pis)
{
Console.WriteLine(pi.Name);
}
通過反射獲得資料表的表名
PropertyAttribute property = (PropertyAttribute)(type.GetCustomAttributes(typeof(PropertyAttribute), false)[0]);
Console.WriteLine(property.tableName);
新增操作的完整代碼:
#region 新增
/// <summary>
/// 新增
/// </summary>
/// <typeparam name="T">實體類型</typeparam>
/// <param name="model">實體資料</param>
/// <param name="isIncludeKeyColumn">主鍵自增時:false、顯式插入主鍵值:ture</param>
/// <param name="connString">連接配接字元串</param>
/// <returns></returns>
public bool Insert<T>(T model, bool isIncludeKeyColumn, string connString) where T : class
{
Type type = typeof(T);
if (type == null)
{
return false;
}
PropertyInfo[] pis = type.GetProperties();
if (pis == null || pis.Length <= 0)
{
return false;
}
//擷取表名
string tableName = GetTableName(type);
if (string.IsNullOrEmpty(tableName))
{
return false;
}
List<string> columns = null;
if (isIncludeKeyColumn == false)
{
//主鍵自增
columns = GetTableColumnsList(pis, ColumnKeyType.Identity | ColumnKeyType.Extend|ColumnKeyType.WidthoutAdd);
}
else
{
//顯式插入主鍵值
columns = GetTableColumnsList(pis, ColumnKeyType.Extend | ColumnKeyType.WidthoutAdd);
}
if (columns == null || columns.Count <= 0)
{
return false;
}
//生成INSERT語句
StringBuilder sqlText = new StringBuilder();
sqlText.Append("INSERT INTO ");
sqlText.Append(tableName);
sqlText.Append(" (");
for (int i = 0; i < columns.Count; i++)
{
sqlText.Append(columns[i]);
if (i < columns.Count - 1)
{
sqlText.Append(",");
}
}
sqlText.Append(") VALUES (");
for (int i = 0; i < columns.Count; i++)
{
sqlText.AppendFormat("@{0}", columns[i]);
if (i < columns.Count - 1)
{
sqlText.Append(",");
}
}
sqlText.Append(");");
SqlParameter[] paras = new SqlParameter[columns.Count];
for (int i = 0; i < paras.Length; i++)
{
PropertyInfo propertyInfo = type.GetProperty(columns[i]);
paras[i] = new SqlParameter(columns[i], GetMySqlDbType(propertyInfo.PropertyType), -1);
paras[i].Value = propertyInfo.GetValue(model, null);
}
return SqlHelper.ExecuteNonQuery(connString, sqlText.ToString(), paras);
}
#endregion
其它操作不再一一列出。
我已将代碼上傳,下載下傳碼是:4DACA2657F
下載下傳碼是啥?如何下載下傳=》三味書屋-基于net6的簡單ORM編碼實作