首页 > 其他分享 >一个简易的ORM框架的实现(二)

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

时间:2023-09-22 16:11:13浏览次数:25  
标签:框架 commodity sqlCommand 简易 connection ORM reader new Id

框架目标

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

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

属性:

  1. 通用性
  2. 健壮性
  3. 稳定性
  4. 扩展性
  5. 高性能
  6. 组件化
  7. 跨平台

从零开始-搭建框架

  1. 建立项目
  2. 主键查询功能开发
  3. 绑定实体

一步一步的给大家推导:
一边写一边测试

从零开始--搭建框架

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]) ;

这里还需要考虑如何避免传入如何的实体,导致报错的问题。
使用基类约束就能避免这个问题了。

标签:框架,commodity,sqlCommand,简易,connection,ORM,reader,new,Id
From: https://www.cnblogs.com/wenlong-4613615/p/17714924.html

相关文章

  • @JsonFormat 使用方法
    @JsonFormat(shape=JsonFormat.Shape.STRING,pattern="yyyy-MM-ddHH:mm:ss",timezone="GMT+8")privateLocalDatecreateTime;错误示范:@JsonFormat(pattern="yyyy-MM-ddHH:mm:ss")privateLocalDatecreateTime;@JsonFormat注解是一......
  • JAVA中三种I/O框架——BIO、NIO、AIO
    一、BIO(BlockingI/O)BIO,同步阻塞IO模型,应用程序发起系统调用后会一直等待数据的请求,直至内核从磁盘获取到数据并拷贝到用户空间;在一般的场景中,多线程模型下的BIO是成本较低、收益较高的方式。但是,如果在高并发的场景下,过多的创建线程,会严重占据系统资源,降低系统对外界响应效率......
  • c# winfrom窗体设置无边框后修改窗体大小 FormBorderStyle设置none后修改窗体大小
    //窗体缩放constintGuying_HTLEFT=10;constintGuying_HTRIGHT=11;constintGuying_HTTOP=12;constintGuying_HTTOPLEFT=13;constintGuying_HTTOPRIGHT=14;constintGuying_HTBOTTOM=15;co......
  • 【Python深度学习】深度学习中框架和模型的区别
        深度学习是人工智能领域的一股强大力量,它的快速发展离不开深度学习框架和模型的进步。本文将介绍深度学习框架和模型的基本概念、它们之间的联系与区别,以及如何根据项目需求选择合适的框架和模型。一、深度学习框架        深度学习框架是进行深度学习研......
  • String.format()的使用
    java.lang.String包下自带的格式化静态方法1.简单示例Stringa=String.format("你好!%s","小扬子");System.out.println(a);输出结果:Hello小扬子%s为占位符标识,s对应字符串类型参数2.对字符串进行格式化Stringa="hello";Stringb="hi";Stringstr=Stri......
  • 完美解决schedule.ScheduleValueError: Invalid time format
    完美解决schedule.ScheduleValueError:Invalidtimeformat文章目录报错问题解决方法声明报错问题之前在工作中遇到过这个坑,记录一下问题以及解决方法,不一定针对所有情况都能用,但是可以供大家参考。问题描述如下:schedule.ScheduleValueError:Invalidtimeformat时间表时间表......
  • 界面组件DevExpress WinForms v23.1 - 富文本编辑器等功能升级
    DevExpressWinForms拥有180+组件和UI库,能为WindowsForms平台创建具有影响力的业务解决方案。DevExpressWinForms能完美构建流畅、美观且易于使用的应用程序,无论是Office风格的界面,还是分析处理大批量的业务数据,它都能轻松胜任!DevExpressWinForm 控件已正式发布v23.1版本,此版......
  • c#Winform窗体实际运行大小与size属性设置不一致问题解决
    privatevoidForm1_Load(objectsender,EventArgse){RectangleScreenArea=System.Windows.Forms.Screen.GetWorkingArea(this);//GetWorkingArea()检索显示器的工作区(工作区是显示器的桌面区域,不包括边界、标题栏、任务栏、停靠窗口和停靠......
  • c# winform 点击窗体任意位置可以拖动
    c#winform窗体,点击窗体标题头可以拖动,如果鼠标点击在里面的panel的时候就没有这个效果了,以下实现拖动的方法。转载自醉低调publicpartialclassForm1:Form{publicForm1(){InitializeComponent();}[DllImport("use......
  • python爬虫简易demo
    以下是一个简单的Python爬虫示例,用于从指定的网页中提取标题和链接:importrequestsfrombs4importBeautifulSoupdefcrawl(url):#发送HTTPGET请求获取网页内容response=requests.get(url)#使用BeautifulSoup解析网页内容soup=BeautifulSoup(r......