框架目標 什麼是框架,框架能做到什麼? 把一個方向的技術研發做封裝,具備通用性,讓使用框架的開發者用起來很輕鬆。 屬性: 通用性 健壯性 穩定性 擴展性 高性能 組件化 跨平臺 從零開始-搭建框架 建立項目 主鍵查詢功能開發 綁定實體 一步一步的給大家推導: 一邊寫一邊測試 從零開始--搭建框架 1 ...
框架目標
什麼是框架,框架能做到什麼?
把一個方向的技術研發做封裝,具備通用性,讓使用框架的開發者用起來很輕鬆。
屬性:
- 通用性
- 健壯性
- 穩定性
- 擴展性
- 高性能
- 組件化
- 跨平臺
從零開始-搭建框架
- 建立項目
- 主鍵查詢功能開發
- 綁定實體
一步一步的給大家推導:
一邊寫一邊測試
從零開始--搭建框架
1. 創建項目
首先,創建兩個類庫一個名為Models保存我們的模型,一個名為DbProxy的類庫保存我們對資料庫的核心操作。
先進行我們查詢功能的編寫,暫時不考慮通用性。
public class DbProxyCore
{
public Commodity GetCommodity(int id)
{
string connectionString = "Data Source=10.10.32.242;Initial Catalog=AdvancedCustomerDB;Persist Security Info=True;User ID=sa;Password=*******";
Commodity commodity = new Commodity();
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
string sql = @"SELECT [Id]
,[ProductId]
,[CategoryId]
,[Title]
,[Price]
,[Url]
,[ImageUrl]
FROM [dbo].[Commodity] where Id="+id;
SqlCommand sqlCommand= connection.CreateCommand();
sqlCommand.CommandText = sql;
SqlDataReader reader= sqlCommand.ExecuteReader();//數據集的讀取器
if (reader.Read())
{
commodity.Id = Convert.ToInt32(reader["Id"]);
commodity.ProductId = Convert.ToInt64(reader["ProductId"]);
commodity.CategoryId = Convert.ToInt32(reader["CategoryId"]);
commodity.Title = reader["Title"].ToString();
commodity.Price = Convert.ToDecimal(reader["Price"]);
commodity.Url = reader["Url"].ToString();
commodity.ImageUrl = reader["ImageUrl"].ToString();
}
}
return commodity;
}
}
當我們又創建一個其他的model對象的時候,就遇到一個問題,難道我們需要每次都進行不同對象的獨有的方法的創建嗎?
並不是,這裡就可以通過泛型來完成它們獨有的方法
暫時的改造
public T Find<T>(int id) where T : new()
{
string connectionString = """
Data Source=10.10.32.242;Initial Catalog=AdvancedCustomerDB;Persist Security Info=True;User ID=sa;Password=*********;
""";
T obj = new T();
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
string sql = @"SELECT [Id]
,[ProductId]
,[CategoryId]
,[Title]
,[Price]
,[Url]
,[ImageUrl]
FROM [dbo].[Commodity] where Id=" + id;
SqlCommand sqlCommand = connection.CreateCommand();
sqlCommand.CommandText = sql;
SqlDataReader reader = sqlCommand.ExecuteReader();//數據集的讀取器
if (reader.Read())
{
//commodity.Id = Convert.ToInt32(reader["Id"]);
//commodity.ProductId = Convert.ToInt64(reader["ProductId"]);
//commodity.CategoryId = Convert.ToInt32(reader["CategoryId"]);
//commodity.Title = reader["Title"].ToString();
//commodity.Price = Convert.ToDecimal(reader["Price"]);
//commodity.Url = reader["Url"].ToString();
//commodity.ImageUrl = reader["ImageUrl"].ToString();
}
}
return obj;
}
嘗試運行,可以正確的運行,並不報錯。
我們要給對象的屬性賦值,不能通過new一個對象,直接調用對象的屬性賦值;
這裡就可以使用到我們的反射技術。
public T Find<T>(int id) where T : new()
{
string connectionString = """
Data Source=10.10.32.242;Initial Catalog=AdvancedCustomerDB;Persist Security Info=True;User ID=sa;Password=7ujm&UJM;
""";
//T obj = new T();
Type type = typeof(T);
object? oResult = Activator.CreateInstance(type);
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
string sql = @"SELECT [Id]
,[ProductId]
,[CategoryId]
,[Title]
,[Price]
,[Url]
,[ImageUrl]
FROM [dbo].[Commodity] where Id=" + id;
SqlCommand sqlCommand = connection.CreateCommand();
sqlCommand.CommandText = sql;
SqlDataReader reader = sqlCommand.ExecuteReader();//數據集的讀取器
if (reader.Read())
{
//commodity.Id = Convert.ToInt32(reader["Id"]);
//commodity.ProductId = Convert.ToInt64(reader["ProductId"]);
//commodity.CategoryId = Convert.ToInt32(reader["CategoryId"]);
//commodity.Title = reader["Title"].ToString();
//commodity.Price = Convert.ToDecimal(reader["Price"]);
//commodity.Url = reader["Url"].ToString();
//commodity.ImageUrl = reader["ImageUrl"].ToString();
foreach (var prop in type.GetProperties())
{
prop.SetValue(oResult, reader[prop.Name]);
}
}
}
return (T)oResult;
}
還有就是sql語句的問題,如何通過T來生成不同的sql語句。
sql語句應該依賴於我們的泛型T,也通過T來動態生成不同的SQl的語句。
public T Find<T>(int id) where T : new()
{
string connectionString = """
Data Source=10.10.32.242;Initial Catalog=AdvancedCustomerDB;Persist Security Info=True;User ID=sa;Password=********;
""";
//T obj = new T();
Type type = typeof(T);
object? oResult = Activator.CreateInstance(type);
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
List<string> propNameList = type.GetProperties().Select(c => c.Name).ToList();
string strProps = string.Join(",", propNameList);
string sql = $"SELECT {strProps} FROM {type.Name} where Id=" + id;
//以逗號分割的資料庫表的欄位名稱。
SqlCommand sqlCommand = connection.CreateCommand();
sqlCommand.CommandText = sql;
SqlDataReader reader = sqlCommand.ExecuteReader();//數據集的讀取器
if (reader.Read())
{
foreach (var prop in type.GetProperties())
{
prop.SetValue(oResult, reader[prop.Name]);
}
}
}
return (T)oResult;
}
處理DBNULL的問題
prop.SetValue(oResult, reader[prop.Name] is DBNull ? null : reader[prop.Name]) ;
這裡還需要考慮如何避免傳入如何的實體,導致報錯的問題。
使用基類約束就能避免這個問題了。