zoukankan      html  css  js  c++  java
  • 手写ORM入门篇(一)

    对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换 。从效果上说,它其实是创建了一个可在编程语言里使用的--“虚拟对象数据库”。

    面向对象是从软件工程基本原则(如耦合、聚合、封装)的基础上发展起来的,而关系数据库则是从数学理论发展而来的,两套理论存在显著的区别。为了解决这个不匹配的现象,对象关系映射技术应运而生。

    对象关系映射(Object-Relational Mapping)提供了概念性的、易于理解的模型化数据的方法。ORM方法论基于三个核心原则: 简单:以最基本的形式建模数据。 传达性:数据库结构被任何人都能理解的语言文档化。 精确性:基于数据模型创建正确标准化的结构。 典型地,建模者通过收集来自那些熟悉应用程序但不熟练的数据建模者的人的信息开发信息模型。建模者必须能够用非技术企业专家可以理解的术语在概念层次上与数据结构进行通讯。建模者也必须能以简单的单元分析信息,对样本数据进行处理。ORM专门被设计为改进这种联系。

    简单的说:ORM相当于中继数据。具体到产品上,例如ADO.NET Entity Framework。DLINQ中实体类的属性[Table]就算是一种中继数据。

    BaseModel示例代码:

    1     public class BaseModel
    2     {
    3         /// <summary>
    4         /// 所有实体的父类,非自增主键GUID
    5         /// </summary>
    6         public string Id { set; get; }
    7     }

    User示例代码:

     1     public class User : BaseModel
     2     {
     3         public string Account { get; set; }
     4 
     5         public string Password { get; set; }
     6 
     7         public string Name { get; set; }
     8 
     9         public int Sex { get; set; }
    10 
    11         public int Status { get; set; }
    12 
    13         public string BizCode { get; set; }
    14 
    15         public DateTime CreateTime { get; set; }
    16 
    17         public string CrateId { get; set; }
    18 
    19         public string TypeName { get; set; }
    20 
    21         public string TypeId { get; set; }
    22 
    23     }

    IBaseDAL示例代码:

     1     public interface IBaseDAL
     2     {
     3         /// <summary>
     4         /// 根据主键返回一个实体
     5         /// </summary>
     6         /// <typeparam name="T"></typeparam>
     7         /// <param name="id"></param>
     8         /// <returns></returns>
     9         T Find<T>(string id) where T : BaseModel;
    10 
    11         /// <summary>
    12         /// 返回一个List<Medel>实体集合
    13         /// </summary>
    14         /// <typeparam name="T"></typeparam>
    15         /// <returns></returns>
    16         List<T> FindAll<T>() where T : BaseModel;
    17 
    18         /// <summary>
    19         /// 添加一条记录
    20         /// </summary>
    21         /// <typeparam name="T"></typeparam>
    22         /// <param name="t"></param>
    23         /// <returns></returns>
    24         bool Add<T>(T t) where T : BaseModel;
    25 
    26         /// <summary>
    27         /// 更新一个实体
    28         /// </summary>
    29         /// <typeparam name="T"></typeparam>
    30         /// <param name="t"></param>
    31         /// <returns></returns>
    32         bool Update<T>(T t) where T : BaseModel;
    33 
    34         /// <summary>
    35         /// 删除一条记录
    36         /// </summary>
    37         /// <typeparam name="T"></typeparam>
    38         /// <param name="t"></param>
    39         /// <returns></returns>
    40         bool Delete<T>(T t) where T : BaseModel;
    41     }

    BaseDAL示例代码

      1     /// <summary>
      2     /// 泛型方法添加BaseModel约束,所有实体类必须有一个非自增的主键Id,Id的值为随机的GUID,
      3     /// </summary>
      4     public class BaseDAL : IBaseDAL
      5     {
      6         /// <summary>
      7         /// 数据库连接字符串
      8         /// </summary>
      9         private static string ConnectionString = ConfigurationManager.ConnectionStrings["OpenAuthDB"].ConnectionString;
     10 
     11         public bool Add<T>(T t) where T : BaseModel
     12         {
     13             Type type = t.GetType();
     14             string columnStr = string.Join(",", type.GetProperties(BindingFlags.Instance | BindingFlags.Public).Select(p => $"[{p.Name}]"));
     15             string valueStr = string.Join(",", type.GetProperties(BindingFlags.Instance | BindingFlags.Public).Select(p => $"@{p.Name}"));
     16             var parameterList = type.GetProperties(BindingFlags.Instance | BindingFlags.Public).Select(p => new SqlParameter($"@{p.Name}", p.GetValue(t) ?? DBNull.Value));
     17             string sqlStr = $"Insert Into [{type.Name}] ({columnStr}) values ({valueStr})";
     18             using (SqlConnection conn = new SqlConnection(ConnectionString))
     19             {
     20                 SqlCommand command = new SqlCommand(sqlStr, conn);
     21                 command.Parameters.AddRange(parameterList.ToArray());
     22                 conn.Open();
     23                 //如果Id是自增的,在sql后面增加个 Select @@Identity; command.ExecuteScalar,新增后把Id拿出来.
     24                 return command.ExecuteNonQuery() > 0;
     25             }
     26         }
     27 
     28         public bool Delete<T>(T t) where T : BaseModel
     29         {
     30             //获取T的类型
     31             Type type = typeof(T);
     32             var parameter = new SqlParameter("Id", type.GetProperty("Id").GetValue(t) ?? DBNull.Value);
     33             string strSql = $"DELETE FROM [{type.Name}] WHERE Id = @Id";
     34             using (SqlConnection conn = new SqlConnection(ConnectionString))
     35             {
     36                 SqlCommand command = new SqlCommand(strSql, conn);
     37                 command.Parameters.Add(parameter);
     38                 conn.Open();
     39                 var iRes = command.ExecuteNonQuery();
     40                 return iRes > 0 ? true : false;
     41             }
     42         }
     43 
     44         public List<T> FindAll<T>() where T : BaseModel
     45         {
     46             Type type = typeof(T);
     47             string sqlStr = $"SELECT {string.Join(",", type.GetProperties().Select(p => $"[{p.Name}]"))} FROM [{type.Name}]";
     48             List<T> list = new List<T>();
     49             using (SqlConnection conn = new SqlConnection(ConnectionString))
     50             {
     51                 SqlCommand command = new SqlCommand(sqlStr, conn);
     52                 conn.Open();
     53                 var reader = command.ExecuteReader();
     54                 while (reader.Read())
     55                 {
     56                     list.Add(this.Trans<T>(type, reader));
     57                 }
     58             }
     59             return list;
     60         }
     61 
     62         public T Find<T>(string id) where T : BaseModel
     63         {
     64             Type type = typeof(T);
     65             string sql = $"SELECT {string.Join(",", type.GetProperties().Select(p => $"[{p.Name}]"))} FROM [{type.Name}] WHERE ID = '{id}' ";
     66             object oObject = Activator.CreateInstance(type);
     67             using (SqlConnection conn = new SqlConnection(ConnectionString))
     68             {
     69                 SqlCommand command = new SqlCommand(sql, conn);
     70                 conn.Open();
     71                 var reader = command.ExecuteReader();
     72                 if (reader.Read())
     73                     return this.Trans<T>(type, reader);
     74                 else
     75                     return default(T);
     76             }
     77         }
     78 
     79         public bool Update<T>(T t) where T : BaseModel
     80         {
     81             Type type = typeof(T);
     82             StringBuilder sb = new StringBuilder();
     83             sb.Append($"UPDATE [{type.Name}] SET ");
     84             var propArray = type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public);
     85             var propArrayLen = propArray.Count();
     86             for (int i = 0; i < propArrayLen; i++)
     87             {
     88                 var propertiesName = propArray[i].Name;
     89                 if (i != propArrayLen - 1)
     90                     sb.Append($"{propertiesName} = @{propertiesName}, ");
     91                 else
     92                     sb.Append($" {propertiesName} = @{propertiesName} ");
     93             }
     94             #region 使用foreach的写法
     95             //foreach (var properties in propArray)
     96             //{
     97             //    var propertiesName = properties.Name;
     98             //    if (i != propArrayLen)
     99             //        sb.Append($"{propertiesName} = @{propertiesName}, ");
    100             //    else
    101             //        sb.Append($" {propertiesName} = @{propertiesName} ");
    102             //    i++;
    103             //}
    104             #endregion
    105             sb.Append($" Where Id = @Id;");
    106             var parameterList = type.GetProperties(BindingFlags.Instance | BindingFlags.Public).Select(p => new SqlParameter($"@{p.Name}", p.GetValue(t) ?? DBNull.Value));
    107             using (SqlConnection conn = new SqlConnection(ConnectionString))
    108             {
    109                 SqlCommand command = new SqlCommand(sb.ToString(), conn);
    110                 command.Parameters.AddRange(parameterList.ToArray());
    111                 conn.Open();
    112                 return command.ExecuteNonQuery() > 0;
    113             }
    114         }
    115 
    116         #region Private Method
    117         private T Trans<T>(Type type, SqlDataReader reader)
    118         {
    119             object oObject = Activator.CreateInstance(type);
    120             foreach (var properties in type.GetProperties())
    121             {
    122                 properties.SetValue(oObject, reader[properties.Name] ?? DBNull.Value);
    123             }
    124             return (T)oObject;
    125         }
    126         #endregion
    127     }

     方法调用示例代码:

     1         static void Main(string[] args)
     2         {
     3             BaseDAL baseDAL = new BaseDAL();
     4             {
     5                 List<User> users = baseDAL.FindAll<User>();
     6                 var b = baseDAL.Delete<User>(new User() {
     7                     Id = "de8be521-f1ec-4483-b124-0be342890507"
     8                 });
     9             }
    10             {
    11                 var b = baseDAL.Add<User>(new User
    12                 {
    13                     Id = Guid.NewGuid().ToString() ,
    14                     Name = "zs",
    15                     Sex = 0,
    16                     Status = 1,
    17                     BizCode = "1234567",
    18                     CrateId = "123456",
    19                     TypeId = "123456",
    20                     TypeName = "admin",
    21                     CreateTime = DateTime.Now,
    22                     Account = "wjl",
    23                     Password = "123456"
    24                 });
    25                 var s = baseDAL.Update<User>(new User
    26                 {
    27                     Id = "4955d7e0-808f-4d50-af66-285e2a18966e",
    28                     Name = "zs",
    29                     Sex = 0,
    30                     Status = 1,
    31                     BizCode = "test value",
    32                     CrateId = "test value",
    33                     TypeId = "test value",
    34                     TypeName = "test value",
    35                     CreateTime = DateTime.Now,
    36                     Account = "test value",
    37                     Password = "test value"
    38                 });
    39             }
    40             Console.ReadLine();
    41         }

     至此,常规的CRUD已基本完成,我们不用再去关注复杂的sql,只需要操作实体类即可。

  • 相关阅读:
    [GDKOI2010] 圈地计划(网络流)
    jzoj3454 表白(love)解题报告(01分数规划+DP)
    数论之卢卡斯定理
    POJ1180 Batch Scheduling 解题报告(斜率优化)
    BZOJ 球形空间产生器 解题报告(高斯消元)
    你是怎么封装一个view的
    沙盒目录结构是怎样的?各自用于那些场景?
    这个写法会出什么问题: @property (copy) NSMutableArray *array;
    怎么用 copy 关键字?
    @property后面可以有哪些修饰符?
  • 原文地址:https://www.cnblogs.com/netlws/p/11028722.html
Copyright © 2011-2022 走看看