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

发布时间 2023-07-26 16:19:39作者: 飘雨的河

一个简易的ORM框架的实现

ORM

ORM---操作数据库---对象关系映射
ORM(Object Relational Mapping)框架采用元数据来描述对象与关系映射的细节。只要提供了持久化类与表的映射关系,ORM框架在运行时就能参照映射文件的信息,把对象持久化到数据库中。

早期数据库操作---ADO.NET

ADO.NET的名称起源于ADO(Active Data Objects),是COM组件库,用于在以往的Mircrosoft技术中访问数据。之所以使用ADO.NET名称,是因为Microsoft希望表明,这是在NET编程环境中优先使用的数据访问接口。
ADO.NET的操作过程
1 连接数据库
2 传递SQL语句
3 数据库执行Sql语句
4 返回执行结果

ADO.NET与ORM的比较
ADO:

  1. 大量的sql语句---业务不同,sql语句不同
  2. 需要根据不同的场景编写不同的代码--- 灵活去编写sql语句 --- 提前优化sql语句 --- 提供高性能的sql语句
  3. 不适合快速开发
  4. 可编程性--- 更加灵活(对于高级开发,全方位发展的)
  5. 高性能---原生---接近于底层
    ORM:
  6. 上手快
  7. 不用关注数据库,不关注sql语句,降低了开发的成本
  8. 关注对象,以对象为核心
  9. 适合快速开发构建
  10. 性能有争议
  11. 生成的sql语句---相对僵化---代码生成器

ORM性能争议

  1. 二次封装---业务的执行,步骤多一些
    2。 映射的过程---必然从类到sql语句变化---类---sql语句---必然会有大量的反射
  2. sql语句僵化---数据库执行有性能损耗

ADO.NET 的增删改查操作

引入我们所需要的nuget包 System.Data.SqlClient
如果我们记不住我们的链接字符串的时候,我们可以通过

连接到我们的数据库,然后通过数据连接中,找到我们所需要的连接字符串

   const string connectString = "Data Source=10.10.33.197;Persist Security Info=True;User ID=sa;Password=********";
    using (SqlConnection connection = new SqlConnection(connectString))
    {
        Console.WriteLine($"状态 {connection.State}");
        connection.Open();
        Console.WriteLine($"状态 {connection.State}");
        connection.Close();
    }

增删改查我们主要分为2类
增删改----受影响行数
查询 ----结果集

增加

 SqlCommand sqlCommand = connection.CreateCommand();
        string sql = @"INSERT INTO
	beauty(id,NAME,sex,borndate,phone,photo,boyfriend_id)
VALUES(13,'唐艺昕','女','1990-4-23','18988888888',NULL,2);
";
        sqlCommand.CommandText = sql;
        int iret=sqlCommand.ExecuteNonQuery();

查询

使用SqlDataReader来获取结果集

SqlCommand sqlCommand = connection.CreateCommand();
        string sql = @" SELECT TOP (1000) [Id]
            ,[ProductId]
            ,[CategoryId]
            ,[Title]
            ,[Price]
            ,[Url]
            ,[ImageUrl]
        FROM [AdvancedCustomerDB].[dbo].[Commodity]";
        sqlCommand.CommandText = sql;
        SqlDataReader sqlDataReader=sqlCommand.ExecuteReader();
        while (sqlDataReader.Read())
        {
            Console.WriteLine(sqlDataReader["Id"]);
            Console.WriteLine(sqlDataReader["ProductId"]);
            Console.WriteLine(sqlDataReader["CategoryId"]);
            Console.WriteLine(sqlDataReader["Title"]);
            Console.WriteLine("=======================================");
        }

使用SqlDataAdapter获取结果集

       SqlCommand sqlCommand = connection.CreateCommand();
        string sql = @" SELECT TOP (1000) [Id]
            ,[ProductId]
            ,[CategoryId]
            ,[Title]
            ,[Price]
            ,[Url]
            ,[ImageUrl]
        FROM [AdvancedCustomerDB].[dbo].[Commodity]";
        SqlCommand cmd = connection.CreateCommand();
        cmd.CommandText = sql;
        cmd.CommandType = System.Data.CommandType.Text;
        SqlDataAdapter adptr = new SqlDataAdapter(cmd);
        System.Data.DataSet ds = new DataSet();
        adptr.Fill(ds, "myds");

        DataTable dt = new DataTable();
        adptr.Fill(dt);

我们在使用上面的语句的时候就遇到了一个问题,什么问题?
就是sql注入的问题,我们没有防备别人使用SQL语句的情况,那我们如何避免这个问题那?
就是SQL语句的参数化。

SqlCommand sqlCommand = connection.CreateCommand();
        string sql = @"INSERT INTO [dbo].[Commodity]
                                                   ([ProductId]
                                                   ,[CategoryId]
                                                   ,[Title]
                                                   ,[Price]
                                                   ,[Url]
                                                   ,[ImageUrl])
                                             VALUES
                                                   (@ProductId
                                                   ,@CategoryId
                                                   ,@Title
                                                   ,@Price
                                                   ,@Url
                                                   ,@ImageUrl)";
        SqlCommand cmd = connection.CreateCommand();
        cmd.CommandText = sql;
        cmd.CommandType = System.Data.CommandType.Text;
        cmd.Parameters.Add(new SqlParameter("@ProductId", "12345798"));
        cmd.Parameters.Add(new SqlParameter("@CategoryId", "234"));
        cmd.Parameters.Add(new SqlParameter("@Title", "高级进阶课程高级进阶课");
        cmd.Parameters.Add(new SqlParameter("@Price", "4799.00"));
        cmd.Parameters.Add(new SqlParameter("@Url", "zhaoxiedu.net"));
        cmd.Parameters.Add(new SqlParameter("@ImageUrl", "zhaoxiedu.net"));
        object insertResult = cmd.ExecuteNonQuery();

事务的问题

 using (SqlTransaction transaction = connection.BeginTransaction())
            {
                try
                {
                    //对于业务上来说,可能同时去操作多次数据库表
                    //要成功--必须要都得成功
                    //ACID
                    //原子性
                    //一致性 --- 要么都成功 只要有一个失败了,都失败了
                    //隔离性
                    //持久性 
                    #region 第一个操作
                    { 
                        string sql = @"Delete [AdvancedCustomerDB].[dbo].[Commodity] where id >@id";
                        SqlCommand cmd = connection.CreateCommand();
                        cmd.Transaction = transaction;
                        cmd.CommandText = sql;
                        cmd.CommandType = System.Data.CommandType.Text;
                        cmd.Parameters.Add(new SqlParameter("@id", 31010));
                        object deleteResult = cmd.ExecuteNonQuery();
                    }
                    #endregion 
                    #region 第二个操作
                    {
                        string sql = @"INSERT INTO [dbo].[Commodity]
                                                   ([ProductId]
                                                   ,[CategoryId]
                                                   ,[Title]
                                                   ,[Price]
                                                   ,[Url]
                                                   ,[ImageUrl])
                                             VALUES
                                                   (@ProductId
                                                   ,@CategoryId
                                                   ,@Title
                                                   ,@Price
                                                   ,@Url
                                                   ,@ImageUrl)";
                        SqlCommand cmd = connection.CreateCommand();
                        cmd.Transaction = transaction;
                        cmd.CommandText = sql;
                        cmd.CommandType = System.Data.CommandType.Text;
                        cmd.Parameters.Add(new SqlParameter("@ProductId", "12345798"));
                        cmd.Parameters.Add(new SqlParameter("@CategoryId", "234"));
                        cmd.Parameters.Add(new SqlParameter("@Title", "高级进阶课程高级进阶课");
                        cmd.Parameters.Add(new SqlParameter("@Price", "4799.00"));
                        cmd.Parameters.Add(new SqlParameter("@Url", "zhaoxiedu.net"));
                        cmd.Parameters.Add(new SqlParameter("@ImageUrl", "zhaoxiedu.net"));
                        object insertResult = cmd.ExecuteNonQuery();
                    }
                    #endregion
                    transaction.Commit();
                }
                catch (Exception ex)
                {
                    transaction.Rollback(); //回滚  可以把之前的操作 全部作废
                    Console.WriteLine(ex.Message);
                } 
            };
        }