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; } } } }