翼度科技»论坛 编程开发 .net 查看内容

一个简易的ORM框架的实现(二)

4

主题

4

帖子

12

积分

新手上路

Rank: 1

积分
12
框架目标

什么是框架,框架能做到什么?

把一个方向的技术研发做封装,具备通用性,让使用框架的开发者用起来很轻松。
属性:

  • 通用性
  • 健壮性
  • 稳定性
  • 扩展性
  • 高性能
  • 组件化
  • 跨平台
从零开始-搭建框架


  • 建立项目
  • 主键查询功能开发
  • 绑定实体
一步一步的给大家推导:
一边写一边测试
从零开始--搭建框架

1. 创建项目

首先,创建两个类库一个名为Models保存我们的模型,一个名为DbProxy的类库保存我们对数据库的核心操作。
先进行我们查询功能的编写,暂时不考虑通用性。
  1. public class DbProxyCore
  2. {
  3.     public Commodity GetCommodity(int id)
  4.     {
  5.         string connectionString = "Data Source=10.10.32.242;Initial Catalog=AdvancedCustomerDB;Persist Security Info=True;User ID=sa;Password=*******";
  6.         Commodity commodity = new Commodity();
  7.         using (var connection = new SqlConnection(connectionString))
  8.         {
  9.             connection.Open();
  10.             string sql = @"SELECT [Id]
  11.                             ,[ProductId]
  12.                             ,[CategoryId]
  13.                             ,[Title]
  14.                             ,[Price]
  15.                             ,[Url]
  16.                             ,[ImageUrl]
  17.                             FROM [dbo].[Commodity] where Id="+id;
  18.             SqlCommand sqlCommand= connection.CreateCommand();
  19.             sqlCommand.CommandText = sql;
  20.             SqlDataReader reader= sqlCommand.ExecuteReader();//数据集的读取器
  21.            
  22.              if (reader.Read())
  23.             {
  24.                 commodity.Id = Convert.ToInt32(reader["Id"]);
  25.                 commodity.ProductId = Convert.ToInt64(reader["ProductId"]);
  26.                 commodity.CategoryId = Convert.ToInt32(reader["CategoryId"]);
  27.                 commodity.Title = reader["Title"].ToString();   
  28.                 commodity.Price = Convert.ToDecimal(reader["Price"]);
  29.                 commodity.Url = reader["Url"].ToString();
  30.                 commodity.ImageUrl = reader["ImageUrl"].ToString();                    
  31.             }
  32.             
  33.         }
  34.         return commodity;
  35.     }
  36. }
复制代码
当我们又创建一个其他的model对象的时候,就遇到一个问题,难道我们需要每次都进行不同对象的独有的方法的创建吗?
并不是,这里就可以通过泛型来完成它们独有的方法
暂时的改造
  1.   public T Find<T>(int id) where T : new()
  2.   {
  3.       string connectionString = """
  4.           Data Source=10.10.32.242;Initial Catalog=AdvancedCustomerDB;Persist Security Info=True;User ID=sa;Password=*********;
  5.           """;
  6.       T obj = new T();
  7.       using (var connection = new SqlConnection(connectionString))
  8.       {
  9.           connection.Open();
  10.           string sql = @"SELECT [Id]
  11.                           ,[ProductId]
  12.                           ,[CategoryId]
  13.                           ,[Title]
  14.                           ,[Price]
  15.                           ,[Url]
  16.                           ,[ImageUrl]
  17.                           FROM [dbo].[Commodity] where Id=" + id;
  18.           SqlCommand sqlCommand = connection.CreateCommand();
  19.           sqlCommand.CommandText = sql;
  20.           SqlDataReader reader = sqlCommand.ExecuteReader();//数据集的读取器
  21.           if (reader.Read())
  22.           {
  23.               //commodity.Id = Convert.ToInt32(reader["Id"]);
  24.               //commodity.ProductId = Convert.ToInt64(reader["ProductId"]);
  25.               //commodity.CategoryId = Convert.ToInt32(reader["CategoryId"]);
  26.               //commodity.Title = reader["Title"].ToString();
  27.               //commodity.Price = Convert.ToDecimal(reader["Price"]);
  28.               //commodity.Url = reader["Url"].ToString();
  29.               //commodity.ImageUrl = reader["ImageUrl"].ToString();
  30.           }
  31.       }
  32.       return obj;
  33.   }
  34.       
复制代码
尝试运行,可以正确的运行,并不报错。
我们要给对象的属性赋值,不能通过new一个对象,直接调用对象的属性赋值;
这里就可以使用到我们的反射技术。
  1.   public T Find<T>(int id) where T : new()
  2.   {
  3.       string connectionString = """
  4.           Data Source=10.10.32.242;Initial Catalog=AdvancedCustomerDB;Persist Security Info=True;User ID=sa;Password=7ujm&UJM;
  5.           """;
  6.       //T obj = new T();
  7.       Type type = typeof(T);
  8.       object? oResult = Activator.CreateInstance(type);
  9.       using (var connection = new SqlConnection(connectionString))
  10.       {
  11.           connection.Open();
  12.           string sql = @"SELECT [Id]
  13.                           ,[ProductId]
  14.                           ,[CategoryId]
  15.                           ,[Title]
  16.                           ,[Price]
  17.                           ,[Url]
  18.                           ,[ImageUrl]
  19.                           FROM [dbo].[Commodity] where Id=" + id;
  20.           SqlCommand sqlCommand = connection.CreateCommand();
  21.           sqlCommand.CommandText = sql;
  22.           SqlDataReader reader = sqlCommand.ExecuteReader();//数据集的读取器
  23.           if (reader.Read())
  24.           {
  25.               //commodity.Id = Convert.ToInt32(reader["Id"]);
  26.               //commodity.ProductId = Convert.ToInt64(reader["ProductId"]);
  27.               //commodity.CategoryId = Convert.ToInt32(reader["CategoryId"]);
  28.               //commodity.Title = reader["Title"].ToString();
  29.               //commodity.Price = Convert.ToDecimal(reader["Price"]);
  30.               //commodity.Url = reader["Url"].ToString();
  31.               //commodity.ImageUrl = reader["ImageUrl"].ToString();
  32.               foreach (var prop in type.GetProperties())
  33.               {                        
  34.                 prop.SetValue(oResult, reader[prop.Name]);
  35.                                                         
  36.               }
  37.           }
  38.       }
  39.       return (T)oResult;
  40.   }
复制代码
还有就是sql语句的问题,如何通过T来生成不同的sql语句。
sql语句应该依赖于我们的泛型T,也通过T来动态生成不同的SQl的语句。
  1. public T Find<T>(int id) where T : new()
  2. {
  3.      string connectionString = """
  4.          Data Source=10.10.32.242;Initial Catalog=AdvancedCustomerDB;Persist Security Info=True;User ID=sa;Password=********;
  5.          """;
  6.      //T obj = new T();
  7.      Type type = typeof(T);
  8.      object? oResult = Activator.CreateInstance(type);
  9.      using (var connection = new SqlConnection(connectionString))
  10.      {
  11.          connection.Open();
  12.          List<string> propNameList = type.GetProperties().Select(c => c.Name).ToList();
  13.          string strProps = string.Join(",", propNameList);
  14.          string sql = $"SELECT {strProps} FROM {type.Name} where Id=" + id;
  15.          //以逗号分割的数据库表的字段名称。
  16.       
  17.          SqlCommand sqlCommand = connection.CreateCommand();
  18.          sqlCommand.CommandText = sql;
  19.          SqlDataReader reader = sqlCommand.ExecuteReader();//数据集的读取器
  20.          if (reader.Read())
  21.          {
  22.              foreach (var prop in type.GetProperties())
  23.              {                        
  24.                prop.SetValue(oResult, reader[prop.Name]);
  25.                                                       
  26.              }
  27.          }
  28.      }
  29.      return (T)oResult;
  30. }
复制代码
处理DBNULL的问题
  1. prop.SetValue(oResult, reader[prop.Name] is DBNull ? null : reader[prop.Name]) ;
复制代码
这里还需要考虑如何避免传入如何的实体,导致报错的问题。
使用基类约束就能避免这个问题了。

来源:https://www.cnblogs.com/wenlong-4613615/archive/2023/09/22/17714924.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具