手写ORM

ORM

对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。本质上就是将数据从一种形式转换到另外一种形式。

在.NET中我门常见的ORM框架有EF,轻量级的ORM Dapper,不管是哪一种框架,他的功能都是一样的,根据对象的映射,将我们写sql这部分转换为操作实体类来完成相应的增删改查。今天我们通过写一个简单的ORM来帮助我们更深层次的了解ORM

一.准备对应的实体类

    [Table("Size")]
    public class Size
    {
        [Column("Name")]
        public string Name { get; set; }
        public string Type { get; set; }
    }

二.定义相应的特性

这写特性主要用来标记类名和属性名,当数据库中的类名与实体类不一致时,可以通过特性标记来对应我们在特性中写的名字。

//定义基类 
public class BaseAttribute : Attribute
    {
        public static string strName = null;
        public BaseAttribute(string name)
        {
            strName = name;
        }
        public string GetName()
        {
            return strName;
        }
    }

 public class TableAttribute:BaseAttribute
    {
        public TableAttribute(string name):base(name)
        {
           
        }
     
    }

  public class ColumnAttribute:BaseAttribute
    {
        public ColumnAttribute(string name):base(name)
        {
         
        }
    }

三.编写获取特性的方法(主要用来获取标记的表名和列名)

   public static class AttributeFunc
    {
        //标记实体类名
        public static string GetTableMappingName(this Type type) //扩展方法
        {
            if (type.IsDefined(typeof(BaseAttribute),true))
            {
                TableAttribute attr = type.GetCustomAttribute<TableAttribute>();
                return attr.GetName(); //获取特性中的名字
            }
            else
            {
                return type.Name;     //特性中没有标记时则采用类名
            }
        }
        //标记属性
        public static string GetColumnMappingName(this MemberInfo info)
        {
            if (info.IsDefined(typeof(BaseAttribute), true))
            {
                ColumnAttribute attr = info.GetCustomAttribute<ColumnAttribute>();
                return attr.GetName();
            }
            else
            {
                return info.Name;
            }
        }
    }

四.写一个简单的查询

  public List<T> FindAll<T>()
        {
            Type type = typeof(T);
            // string clumnString = string.Join(",", type.GetProperties().Select(x => $"[{x.Name}]"));
            //这里将x.Name替换为x.GetColumnMappingName也就是上面写的获取特性的方法。根据判断是否标记特性来取特性名。这里使用了一个扩展方法,所以能直接通过类型打点调用
            string clumnString = string.Join(",", type.GetProperties().Select(x => $"[{x.GetColumnMappingName()}]"));
            string sql = $"select {clumnString} from {type.GetTableMappingName()}";  //拼装sql
            //string sql = $"select {clumnString} from {type.Name}";

            using (SqlConnection connection = new SqlConnection(_connectionString))
            {
                using (SqlCommand cmd = new SqlCommand(sql, connection))
                {
                    try
                    {
                        connection.Open();
                        SqlDataReader reader = cmd.ExecuteReader();
                        List<T> list = new List<T>();
                        while (reader.Read())
                        {
                            T t = (T)Activator.CreateInstance(type);//创建对象
                            foreach (var prop in type.GetProperties())
                            {
                                prop.SetValue(t, reader[prop.Name] is DBNull?null: reader[prop.Name]); //属性赋值
                            }
                            list.Add(t);
                        }
                        return list;
                       
                    }
                    catch (System.Data.SqlClient.SqlException e)
                    {
                        connection.Close();
                        throw e;
                    }
                }
            }
        }
原文地址:https://www.cnblogs.com/HTLucky/p/13157992.html