1 /// <summary>
2 /// 执行Sql语句
3 /// </summary>
4 public static class DatabaseExtend
5 {
6 /// <summary>
7 /// 执行任何SQL语句,通用所有的数据库(SQLServer,MySql,Oracle等),利用EMIT快速反射,得到动态类型实体,支持参数查询,防止sql注入。 Created by ZhangQC
8 /// </summary>
9 /// <param name="db">数据库操作</param>
10 /// <param name="sql">执行的sql命令</param>
11 /// <param name="parameters">参数</param>
12 /// <param name="serverName">sql服务提供者</param>
13 /// <returns></returns>
14 public static IEnumerable SqlQueryForDynamic(this Database db, string sql, SystemEnum.DataProvider serverName = SystemEnum.DataProvider.MySql, params object[] parameters)
15 {
16 //获取数据库连接提供者
17 IDbConnection defaultConn = GetConnection(serverName);
18 return SqlQueryForDynamicOtherDb(db, sql, defaultConn, parameters);
19 }
20
21 public static IEnumerable<T> SqlQueryForSpecificType<T>(this Database db, string sql,SqlParameter[] parameters,
22 SystemEnum.DataProvider serverName = SystemEnum.DataProvider.SqlServer)
23 {
24 //获取数据库连接提供者
25 IDbConnection defaultConn = GetConnection(serverName);
26 return SqlQueryForSpecificTypeOtherDb<T>(db, sql, defaultConn, parameters);
27 }
28
29
30
31 /// <summary>
32 /// 获取连接字符串 Created by ZhangQC
33 /// </summary>
34 /// <param name="providerType"></param>
35 /// <returns></returns>
36 public static IDbConnection GetConnection(SystemEnum.DataProvider providerType)
37 {
38 IDbConnection iDbConnection;
39 switch (providerType)
40 {
41 case SystemEnum.DataProvider.SqlServer:
42 iDbConnection = new SqlConnection();
43 break;
44 case SystemEnum.DataProvider.OleDb:
45 iDbConnection = new OleDbConnection();
46 break;
47 case SystemEnum.DataProvider.Odbc:
48 iDbConnection = new OdbcConnection();
49 break;
50 case SystemEnum.DataProvider.Oracle:
51 //iDbConnection = new OracleConnection();
52 iDbConnection = new SqlConnection();
53 break;
54 case SystemEnum.DataProvider.MySql:
55 //iDbConnection = new MySqlConnection();
56 iDbConnection = new SqlConnection();
57 break;
58 default:
59 return null;
60 }
61 return iDbConnection;
62 }
63
64 /// <summary>
65 /// 执行sql语句,要求提供接受实体
66 /// </summary>
67 /// <typeparam name="T"></typeparam>
68 /// <param name="db"></param>
69 /// <param name="sql"></param>
70 /// <param name="conn"></param>
71 /// <param name="parameters"></param>
72 /// <returns></returns>
73 public static IEnumerable<T> SqlQueryForSpecificTypeOtherDb<T>(this Database db, string sql, IDbConnection conn,
74 object[] parameters)
75 {
76 if (parameters != null)
77 {
78 return db.SqlQuery<T>(sql, parameters).Cast<T>().ToList();
79 }
80 return db.SqlQuery<T>(sql).ToList();
81 }
82
83
84
85
86 /// <summary>
87 /// 使用反射发出(快速反射EMIT)动态创建返回 Created by ZhangQC
88 /// </summary>
89 /// <param name="db"></param>
90 /// <param name="sql"></param>
91 /// <param name="conn"></param>
92 /// <param name="parameters"></param>
93 /// <returns></returns>
94 public static IEnumerable SqlQueryForDynamicOtherDb(this Database db, string sql, IDbConnection conn, params object[] parameters)
95 {
96 conn.ConnectionString = db.Connection.ConnectionString;
97
98 if (conn.State != ConnectionState.Open)
99 {
100 conn.Open();
101 }
102
103 IDbCommand cmd = conn.CreateCommand();
104
105 cmd.CommandText = sql;
106 //开启防止SQL注入,这里万分重要啊 ZhangqC
107 if (parameters != null)
108 {
109 foreach (var obj in parameters)
110 {
111 cmd.Parameters.Add(obj);
112 }
113 }
114
115 IDataReader dataReader = cmd.ExecuteReader();
116
117 if (!dataReader.Read())
118 {
119 return null; //无结果返回Null
120 }
121
122 #region 构建动态字段
123
124 TypeBuilder builder = CreateTypeBuilder("EF_DynamicModelAssembly", "DynamicModule", "DynamicType");
125
126 int fieldCount = dataReader.FieldCount;
127 for (int i = 0; i < fieldCount; i++)
128 {
129 //此处类型需要特殊处理(比较尴尬,需要优化)
130 if (dataReader.GetFieldType(i) == typeof(decimal))
131 {
132 CreateAutoImplementedProperty(builder, dataReader.GetName(i), typeof(decimal?));
133 }
134 else if (dataReader.GetFieldType(i) == typeof(DateTime))
135 {
136 CreateAutoImplementedProperty(builder, dataReader.GetName(i), typeof(DateTime?));
137 }
138 else if (dataReader.GetFieldType(i) == typeof(int))
139 {
140 CreateAutoImplementedProperty(builder, dataReader.GetName(i), typeof(int?));
141 }
142 else
143 {
144 CreateAutoImplementedProperty(builder, dataReader.GetName(i), dataReader.GetFieldType(i));
145 }
146 }
147
148 #endregion
149
150 dataReader.Close();
151 dataReader.Dispose();
152 cmd.Dispose();
153 conn.Close();
154 conn.Dispose();
155
156 Type returnType = builder.CreateType();
157
158 if (parameters != null)
159 {
160 var result= db.SqlQuery(returnType, sql, parameters);
161 //解决循环调用的报错问题
162 cmd.Parameters.Clear();
163 return result;
164 }
165 else
166 {
167 return db.SqlQuery(returnType, sql);
168 }
169 }
170
171 /// <summary>
172 /// 动态创建程序集 ZhangQC
173 /// </summary>
174 /// <param name="assemblyName"></param>
175 /// <param name="moduleName"></param>
176 /// <param name="typeName"></param>
177 /// <returns></returns>
178 public static TypeBuilder CreateTypeBuilder(string assemblyName, string moduleName, string typeName)
179 {
180 TypeBuilder typeBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
181 new AssemblyName(assemblyName),
182 AssemblyBuilderAccess.Run).DefineDynamicModule(moduleName).DefineType(typeName,
183 TypeAttributes.Public);
184 typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
185 return typeBuilder;
186 }
187
188
189 /// <summary>
190 /// 动态创建实体 ZhangQC
191 /// </summary>
192 /// <param name="builder"></param>
193 /// <param name="propertyName"></param>
194 /// <param name="propertyType"></param>
195 public static void CreateAutoImplementedProperty(TypeBuilder builder, string propertyName, Type propertyType)
196 {
197 const string privateFieldPrefix = "m_";
198 const string getterPrefix = "get_";
199 const string setterPrefix = "set_";
200
201
202
203 // Generate the field.
204 FieldBuilder fieldBuilder = builder.DefineField(
205 string.Concat(
206 privateFieldPrefix, propertyName),
207 propertyType,
208 FieldAttributes.Private);
209
210 // Generate the property
211 PropertyBuilder propertyBuilder = builder.DefineProperty(
212 propertyName,
213 System.Reflection.PropertyAttributes.HasDefault,
214 propertyType, null);
215
216 // Property getter and setter attributes.
217 MethodAttributes propertyMethodAttributes = MethodAttributes.Public
218 | MethodAttributes.SpecialName
219 | MethodAttributes.HideBySig;
220
221 // Define the getter method.
222 MethodBuilder getterMethod = builder.DefineMethod(
223 string.Concat(
224 getterPrefix, propertyName),
225 propertyMethodAttributes,
226 propertyType,
227 Type.EmptyTypes);
228
229 // Emit the IL code.
230 // ldarg.0
231 // ldfld,_field
232 // ret
233 ILGenerator getterIlCode = getterMethod.GetILGenerator();
234 getterIlCode.Emit(OpCodes.Ldarg_0);
235 getterIlCode.Emit(OpCodes.Ldfld, fieldBuilder);
236 getterIlCode.Emit(OpCodes.Ret);
237
238 // Define the setter method.
239 MethodBuilder setterMethod = builder.DefineMethod(
240 string.Concat(setterPrefix, propertyName),
241 propertyMethodAttributes,
242 null,
243 new Type[] { propertyType });
244
245 // Emit the IL code.
246 // ldarg.0
247 // ldarg.1
248 // stfld,_field
249 // ret
250 ILGenerator setterIlCode = setterMethod.GetILGenerator();
251 setterIlCode.Emit(OpCodes.Ldarg_0);
252 setterIlCode.Emit(OpCodes.Ldarg_1);
253 setterIlCode.Emit(OpCodes.Stfld, fieldBuilder);
254 setterIlCode.Emit(OpCodes.Ret);
255
256 propertyBuilder.SetGetMethod(getterMethod);
257 propertyBuilder.SetSetMethod(setterMethod);
258 }
259 }