·您现在的位置: 云翼网络 >> 文章中心 >> 网站建设 >> 网站建设开发 >> ASP.NET网站开发 >> 1.连接字符串的创建-Lazy.Framework从零开始设计自己的ORM架构
注册了博客园已经有几个月了,却从来都没有上来过,本人大概从2010年开始就开始做.NET 方向的开发。
这个是我在博客园发布的第一个帖子。 主要就是说说最近在写的一个ORM架构。
本人接触的ORM架构也有不少,没有一个是用着顺手的,要么就是配置起来特别吃力,要么就是使用起来不是很方便。 最终还是比较喜欢NHibernate这套架构,因为这套架构支持在Model表的实体类内部包含其他的表的实体类 也就是在使用的时候,连联表查询都可以省了 可以直接支持对象.对象的方式来进行查询数据,屡试不爽,有了它基本已经放弃了使用视图 或 联表查询等等。
但是用它也有不爽的地方,就是配置起来太麻烦,需要些HQL。
出于以上种种,想自己动手开发一套,高性能高效率的ORM架构。
废话不多说,下面开始说我的构思。、
开发一套架构的开始,总是要有一套架构的构思的。
对于这套架构,在实体类中舍去了xml文件的配置,使用了自定义特性。
1. 用户发起了一个添加对象的操作
2. 通过添加的该对象T,去缓存中获取T对象相关的全部自定义特性,如果缓存中不存在则获取该T对象的自定义特性存入缓存中
3. 找到T对象,在去缓存中获取T-sql语句 由于数据库不同,所以生成的Sql语句也不相同,如果不存在则新生成,然后放入缓存中。
4. 获取到了T-SQL语句后,使用T对象生成 DbParameter[] 使用Emit,动态的创建IL 创建获取T对象属性的方法,来进行将T 填充到DbParameter[]
5. 通过T对应的配置文件的数据库连接,实例化不同的数据库
6. 实例化数据库成功后 来进行执行插入
7. 如果插入的对象 T 是要缓存的话, 将会同时存入内存数据库
8. 上述描述的是 添加对象 并不包含获取对象 如果是获取对象的话,需要用到AOP 来实现 对象.对象
太专业的话也不会说,大概的流程是这样的一个流程,实现思路也大概有了一些,先从最底层开始写起,那就是配置文件中的数据库连接字符串
下面是Config 配置文件中的数据库连接字符串
<?xml version="1.0" encoding="utf-8" ?> <configuration> <connectionStrings> <add name="Lazy1" connectionString="server=.=sa;pwd=Dieyu;database=Lazy.Framework;" PRoviderName="System.Data.SqlClient"/> <add name="Lazy2" connectionString="server=.=sa;pwd=Dieyu;database=Lazy;" providerName="System.Data.SqlClient"/> </connectionStrings> </configuration>
下述代码 是先创建了 配置节点的接口
1 /// <summary> 2 /// <para>代码说明:</para> 3 /// <para> 数据库连接字符串接口,用户存储数据库的连接字符串,主要应用于 配置文件的 connectionStrings 的节点数据库获取</para> 4 /// <para>使用示例:</para> 5 /// <para> 无</para> 6 /// </summary> 7 public interface ILazyConfiguration 8 { 9 /// <summary> 10 /// <para>代码说明:</para> 11 /// <para> 用于设置获取该对象的唯一标识</para> 12 /// <para>使用示例:</para> 13 /// <para> 无</para> 14 /// </summary> 15 string Name { get; set; } 16 /// <summary> 17 /// <para>代码说明:</para> 18 /// <para> 用于设置数据库的连接字符串</para> 19 /// <para>使用示例:</para> 20 /// <para> 如:ConnectionString = "server=.;uid=sa......省略"</para> 21 /// </summary> 22 string ConnectionString { get; set; } 23 /// <summary> 24 /// <para>代码说明:</para> 25 /// <para> 用于设置该对象要连接数据库的类型</para> 26 /// <para>使用示例:</para> 27 /// <para> 如:ProviderName = "System.Data.SqlClient"</para> 28 /// </summary> 29 string ProviderName { get; set; } 30 /// <summary> 31 /// <para>代码说明:</para> 32 /// <para> 用于设置该对象要连接数据库的类型</para> 33 /// <para>使用示例:</para> 34 /// <para> 如:DataType = DataType.System_Data_SqlClient</para> 35 /// </summary> 36 LazyDataTypeEnum DataType { get; set; } 37 }
下面是集成了接口的配置类
1 /// <summary> 2 /// <para>代码说明:</para> 3 /// <para> 数据库连接字符串对象,用户存储数据库的连接字符串,主要应用于 配置文件的 connectionStrings 的节点数据库获取</para> 4 /// <para>使用示例:</para> 5 /// <para> 无</para> 6 /// </summary> 7 internal partial class LazyConfiguration : ILazyConfiguration 8 { 9 /// <summary> 10 /// 配置节点名称,此键唯一,不能拥有重复 11 /// </summary> 12 public string Name { get; set; } 13 /// <summary> 14 /// <para>代码说明:</para> 15 /// <para> 配置节点字符串</para> 16 /// <para>使用示例:</para> 17 /// <para> 如:ConnectionString = "server=.;uid=sa......省略"</para> 18 /// </summary> 19 public string ConnectionString { get; set; } 20 /// <summary> 21 /// <para>代码说明:</para> 22 /// <para> 配置节点要连接的数据库驱动</para> 23 /// <para>使用示例:</para> 24 /// <para> 如:ProviderName = "System.Data.SqlClient"</para> 25 /// </summary> 26 public string ProviderName { get; set; } 27 /// <summary> 28 /// <para>代码说明:</para> 29 /// <para> 用于设置该对象要连接数据库的类型</para> 30 /// <para>使用示例:</para> 31 /// <para> 如:DataType = DataType.System_Data_SqlClient</para> 32 /// </summary> 33 public LazyDataTypeEnum DataType { get; set; } 34 }
当配置节点类与接口都创建完成了后 由于是多个数据库连接串, 我们需要创捷 节点类的集合
1 /// <summary> 2 /// <para>代码说明:</para> 3 /// <para> 配置节点访问集合,用来获取数据库连接字符串的节点信息</para> 4 /// <para>使用示例:</para> 5 /// <para> 只提供程序集内部使用,外部访问无效</para> 6 /// </summary> 7 public class LazyConfigurationCollection : IEnumerable 8 { 9 #region <<私有属性>> 10 /// <summary> 11 /// 私有静态集合,用于保证全局唯一性 12 /// </summary> 13 private static IList<ILazyConfiguration> listLazyConfiguration = new List<ILazyConfiguration>(); 14 #endregion 15 16 #region <<公共属性>> 17 /// <summary> 18 /// <para>代码说明:</para> 19 /// <para> 通过索引获取一个ILazyConfiguration对象</para> 20 /// <para>使用示例:</para> 21 /// <para> 如:ILazyConfiguration[0]</para> 22 /// </summary> 23 /// <param name="index">索引位置</param> 24 /// <returns>ILazyConfiguration对象</returns> 25 public ILazyConfiguration this[int index] 26 { 27 get 28 { 29 return listLazyConfiguration[index]; 30 } 31 } 32 /// <summary> 33 /// <para>代码说明:</para> 34 /// <para> 通过名称获取一个ILazyConfiguration对象</para> 35 /// <para>使用示例:</para> 36 /// <para> 如:ILazyConfiguration["LazySql......."]</para> 37 /// </summary> 38 /// <param name="name">要获取连接字符串的名称</param> 39 /// <returns>ILazyConfiguration对象</returns> 40 public ILazyConfiguration this[string name] 41 { 42 get 43 { 44 return listLazyConfiguration.FirstOrDefault(P => P.Name == name); 45 } 46 } 47 /// <summary> 48 /// <para>代码说明:</para> 49 /// <para> 返回序列中的第一个元素;如果序列中不包含任何元素,则返回默认值。</para> 50 /// <para>使用示例:</para> 51 /// <para> 无</para> 52 /// </summary> 53 public ILazyConfiguration FirstOrDefaultConfiguration 54 { 55 get 56 { 57 return listLazyConfiguration.FirstOrDefault(); 58 } 59 } 60 /// <summary> 61 /// <para>代码说明:</para> 62 /// <para> 返回集合的总数</para> 63 /// <para>使用示例:</para> 64 /// <para> 如:ILazyConfiguration.Count</para> 65 /// </summary> 66 public int Count 67 { 68 get 69 { 70 return listLazyConfiguration.Count; 71 } 72 } 73 #endregion 74 75 #region <<构造函数>> 76 /// <summary> 77 /// <para>代码说明:</para> 78 /// <para> 实例化一个新的对象,该构造函数只能有程序集内部访问</para> 79 /// <para>使用示例:</para> 80 /// <para> 无</para> 81 /// </summary> 82 internal LazyConfigurationCollection() 83 { 84 //无 85 } 86 #endregion 87 88 #region <<私有方法>> 89 /// <summary> 90 /// <para>代码说明:</para> 91 /// <para> 向集合内添加一个对象</para> 92 /// <para>使用示例:</para> 93 /// <para> 无</para> 94 /// </summary> 95 /// <param name="item">ILazyConfiguration对象</param> 96 internal void Add(ILazyConfiguration item) 97 { 98 listLazyConfiguration.Add(item); 99 } 100 #endregion 101 102 #region <<公共方法>> 103 /// <summary> 104 /// <para>代码说明:</para> 105 /// <para> 返回一个循环访问集合的枚举器,可用于linq等查询</para> 106 /// <para>使用示例:</para> 107 /// <para> 无</para> 108 /// </summary> 109 public IEnumerator GetEnumerator() 110 { 111 return listLazyConfiguration.GetEnumerator(); 112 } 113 #endregion 114 }
节点集合创建完成后 , 我们需要一个单利模式, 来永远的保存着这些节点
1 /// <summary> 2 /// <para>代码说明:</para> 3 /// <para> 获取配置节配置的数据库连接字符串,该类只会被全局实例化一次</para> 4 /// <para>使用示例:</para> 5 /// <para> LazyConfigurationProperty LazyConfigurationProperty = LazyConfigurationProperty.GetLazyConfigurationProperty()</para> 6 /// </summary> 7 public sealed class LazyConfigurationProperty 8 { 9 #region <<私有属性>> 10 /// <summary> 11 /// 创建全为唯一私有lazyConfigurationProperty 对象 12 /// </summary> 13 private static LazyConfigurationProperty lazyConfigurationProperty; 14 /// <summary> 15 /// 程序运行时,创建一个静态只读的进程辅助对象 16 /// </summary> 17 private static readonly object _object = new object(); 18 #endregion 19 20 #region <<公共属性>> 21 /// <summary> 22 /// <para>代码说明:</para> 23 /// <para> 获取配置文件的配置节的集合</para> 24 /// <para>使用示例:</para> 25 /// <para> 如:LazyConfigurations["xx"] or LazyConfigurations[i].....</para> 26 /// </summary> 27 public LazyConfigurationCollection LazyConfigurations { get; private set; } 28 #endregion 29 30 #region <<构造函数>> 31 /// <summary> 32 /// 构造方法私有,外键不能通过New类实例化此类 33 /// </summary> 34 private LazyConfigurationProperty() { } 35 #endregion 36 37 #region <<公共方法>> 38 /// <summary> 39 /// <para>代码说明:</para> 40 /// <para> 单例模式,数据库配置对象, 全局唯一创建对象的入口</para> 41 /// <para>使用示例:</para> 42 /// <para> LazyConfigurationProperty LazyConfigurationProperty = LazyConfigurationProperty.GetLazyConfigurationProperty()</para> 43 /// </summary> 44 /// <returns>LazyConfigurationProperty全局唯一对象</returns> 45 public static LazyConfigurationProperty GetLazyConfigurationProperty() 46 { 47 //先判断实例是否存在,不存在再加锁处理 48 if (lazyConfigurationProperty == null) 49 { 50 //在同一时刻加了锁的那部分程序只有一个线程可以进入, 51 lock (_object) 52 { 53 //如实例不存在,则New一个新实例,否则返回已有实例 54 if (lazyConfigurationProperty == null) 55 { 56 lazyConfigurationProperty = new LazyConfigurationProperty(); 57 //配置节点集合 58 lazyConfigurationProperty.LazyConfigurations = new LazyConfigurationCollection(); 59 60 //像LazyConfigurationCollection添加对象 61 var LazyConfigurationList = SettingConnectionStrings.GetConnectionStrings(); 62 foreach (var item in LazyConfigurationList) 63 { 64 lazyConfigurationProperty.LazyConfigurations.Add(item); 65 } 66 } 67 } 68 } 69 return lazyConfigurationProperty; 70 } 71 #endregion 72 }
当此上述类被构建时 , 调用了下面类的方法, 将所有连接字符串 都装入上述类的集合中
1 /// <summary> 2 /// <para>代码说明:</para> 3 /// <para> 配置文件对象初始化类,检查配置文件,初始化连接对象</para> 4 /// <para>使用示例:</para> 5 /// <para> 如:SettingConnectionStrings.GetLazyConnectionStrings()</para> 6 /// </summary> 7 internal sealed class SettingConnectionStrings 8 { 9 /// <summary> 10 /// <para>代码说明:</para> 11 /// <para> 获取配置文件中的ConnectionStrings节中的全部数据中的Lazy配置集合</para> 12 /// <para>使用示例:</para> 13 /// <para> 如:SettingConnectionStrings.GetLazyConnectionStrings()</para> 14 /// </summary> 15 /// <returns>返回Lazy配置集合</returns> 16 internal static IEnumerable<ConnectionStringSettings> GetLazyConnectionStrings() 17 { 18 //获取全部数据库连接 19 var _ConnectionStrings = ConfigurationManager.ConnectionStrings; 20 //获取数据库配置的连接字符串 21 var _LazyConnectionStrings = _ConnectionStrings.Cast<ConnectionStringSettings>().Where(P => P.Name.IndexOf("Lazy") == 0); 22 if (_LazyConnectionStrings.Count() <= 0) 23 { 24 //如果未配置任何连接字符串,则出现此异常 25 throw new ArgumentNullException("connectionStrings", "在配置文件中, connectionStrings 节点,并不包含数据库连接字符串的配置, 要解决此错误,需要在配置文件中 connectionStrings 节点内添加 \"name\" 以 Lazy 开头的节点配置"); 26 } 27 28 return _LazyConnectionStrings; 29 } 30 /// <summary> 31 /// <para>代码说明:</para> 32 /// <para> 获取配置文件中的ConnectionStrings节中的全部数据中的Lazy配置集合</para> 33 /// <para>使用示例:</para> 34 /// <para> 如:SettingConnectionStrings.GetConnectionStrings()</para> 35 /// </summary> 36 /// <returns>返回Lazy配置集合</returns> 37 internal static IList<ILazyConfiguration> GetConnectionStrings() 38 { 39 //获取节点集合 40 var _ConnectionStringSettingsList = GetLazyConnectionStrings(); 41 //设置返回集合 42 IList<ILazyConfiguration> _LazyConfigurationList = new List<ILazyConfiguration>(); 43 foreach (ConnectionStringSettings connectionStringSettings in _ConnectionStringSettingsList) 44 { 45 LazyDataTypeEnum _LazyDataType; 46 try 47 { 48 //将ProviderName转换成枚举,如果失败则触发异常 49 _LazyDataType = (LazyDataTypeEnum)Enum.Parse(typeof(LazyDataTypeEnum),connectionStringSettings.ProviderName.Replace('.', '_')); 50 } 51 catch 52 { 53 //如果无法转换为枚举 , 则引发异常. 54 StringBuilder _ErrorMsg =new StringBuilder(); 55 _ErrorMsg.Append("在位置文件中,connectionStrings 节点下的子节点,并不包含 \"ProviderName\" 的属性配置,或并不属于以下的一种:\n"); 56 _ErrorMsg.Append("System.Data.Odbc\n"); 57 _ErrorMsg.Append("System.Data.OleDb\n"); 58 _ErrorMsg.Append("System.Data.OracleClient\n"); 59 _ErrorMsg.Append("System.Data.SqlClient\n"); 60 _ErrorMsg.Append("MySQL.Data.MySqlClient\n"); 61 _ErrorMsg.Append(" 要解决此问题,请按此配置,如下\n"); 62 _ErrorMsg.Append(" <add name=\"LazySqlConnection\" connectionString=\"server=....省略;\" providerName=\"System.Data.SqlClient\" />\n"); 63 throw new ArgumentNullException("ProviderName", _ErrorMsg.ToString()); 64 } 65 66 if (_LazyConfigurationList.Count(P => P.Name == connectionStringSettings.Name) > 0) 67 { 68 throw new ArgumentNullException("Name", "在配置文件中, connectionStrings 节点,存在相同 \"name\" 的节点."); 69 } 70 71 //添加集合 72 _LazyConfigurationList.Add(new LazyConfiguration() 73 { 74 ConnectionString = connectionStringSettings.ConnectionString, 75 Name = connectionStringSettings.Name, 76 ProviderName = connectionStringSettings.ProviderName, 77 DataType = _LazyDataType 78 }); 79 80 } 81 return _LazyConfigurationList; 82 } 83 }
上面代码是写关于 配置连接字符串的存储
下面再放入一个数据库类型的枚举
1 /// <summary> 2 /// <para>代码说明:</para> 3 /// <para> 数据库类型枚举</para> 4 /// <para>使用示例:</para> 5 /// <para> LazyDataTypeEnum.SQLServer</para> 6 /// </summary> 7 public enum LazyDataTypeEnum 8 { 9 /// <summary> 10 /// System.Data.Odbc 11 /// </summary> 12 System_Data_Odbc, 13 /// <summary> 14 /// System.Data.OleDb 15 /// </summary> 16 System_Data_OleDb, 17 /// <summary> 18 /// System.Data.OracleClient 19 /// </summary> 20 System_Data_OracleClient, 21 /// <summary> 22 /// System.Data.SqlClient 23 /// </summary> 24 System_Data_SqlClient, 25 /// <summary> 26 /// MySql.Data.MySqlClient 27 /// </summary> 28 MySql_Data_MySqlClient 29 30 }
第一天,相关连接字符串的存储 就先写到这里 欢迎指点。