Mercurial > pub > bltoolkit
comparison Source/Data/DbManager.Linq.cs @ 0:f990fcb411a9
Копия текущей версии из github
author | cin |
---|---|
date | Thu, 27 Mar 2014 21:46:09 +0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f990fcb411a9 |
---|---|
1 using System; | |
2 using System.Collections.Generic; | |
3 using System.Data; | |
4 using System.Linq; | |
5 using System.Reflection; | |
6 using System.Text; | |
7 | |
8 using BLToolkit.Aspects; | |
9 | |
10 namespace BLToolkit.Data | |
11 { | |
12 using DataProvider; | |
13 using Linq; | |
14 using Sql; | |
15 using Sql.SqlProvider; | |
16 | |
17 public partial class DbManager : IDataContext | |
18 { | |
19 public Table<T> GetTable<T>() | |
20 where T : class | |
21 { | |
22 return new Table<T>(this); | |
23 } | |
24 | |
25 public Table<T> GetTable<T>(bool dispose) | |
26 where T : class | |
27 { | |
28 return new Table<T>(new DataContextInfo(this, dispose)); | |
29 } | |
30 | |
31 public Table<T> GetTable<T>(object instance, [NotNull]MethodInfo methodInfo, [NotNull] params object[] parameters) | |
32 where T : class | |
33 { | |
34 return Linq.Extensions.GetTable<T>(this, instance, methodInfo, parameters); | |
35 } | |
36 | |
37 class PreparedQuery | |
38 { | |
39 public string[] Commands; | |
40 public List<SqlParameter> SqlParameters; | |
41 public IDbDataParameter[] Parameters; | |
42 public SqlQuery SqlQuery; | |
43 public ISqlProvider SqlProvider; | |
44 } | |
45 | |
46 #region SetQuery | |
47 | |
48 object IDataContext.SetQuery(IQueryContext queryContext) | |
49 { | |
50 var query = GetCommand(queryContext); | |
51 | |
52 GetParameters(queryContext, query); | |
53 | |
54 if (TraceSwitch.TraceInfo) | |
55 WriteTraceLine(((IDataContext)this).GetSqlText(query).Replace("\r", ""), TraceSwitch.DisplayName); | |
56 | |
57 return query; | |
58 } | |
59 | |
60 PreparedQuery GetCommand(IQueryContext query) | |
61 { | |
62 if (query.Context != null) | |
63 { | |
64 return new PreparedQuery | |
65 { | |
66 Commands = (string[])query.Context, | |
67 SqlParameters = query.SqlQuery.Parameters, | |
68 SqlQuery = query.SqlQuery | |
69 }; | |
70 } | |
71 | |
72 var sql = query.SqlQuery.ProcessParameters(); | |
73 | |
74 var newSql = ProcessQuery(sql); | |
75 | |
76 if (sql != newSql) | |
77 { | |
78 sql = newSql; | |
79 sql.IsParameterDependent = true; | |
80 } | |
81 | |
82 var sqlProvider = DataProvider.CreateSqlProvider(); | |
83 | |
84 var cc = sqlProvider.CommandCount(sql); | |
85 var sb = new StringBuilder(); | |
86 | |
87 var commands = new string[cc]; | |
88 | |
89 for (var i = 0; i < cc; i++) | |
90 { | |
91 sb.Length = 0; | |
92 | |
93 sqlProvider.BuildSql(i, sql, sb, 0, 0, false); | |
94 commands[i] = sb.ToString(); | |
95 } | |
96 | |
97 if (!query.SqlQuery.IsParameterDependent) | |
98 query.Context = commands; | |
99 | |
100 return new PreparedQuery | |
101 { | |
102 Commands = commands, | |
103 SqlParameters = sql.Parameters, | |
104 SqlQuery = sql, | |
105 SqlProvider = sqlProvider | |
106 }; | |
107 } | |
108 | |
109 protected virtual SqlQuery ProcessQuery(SqlQuery sqlQuery) | |
110 { | |
111 return sqlQuery; | |
112 } | |
113 | |
114 void GetParameters(IQueryContext query, PreparedQuery pq) | |
115 { | |
116 var parameters = query.GetParameters(); | |
117 | |
118 if (parameters.Length == 0 && pq.SqlParameters.Count == 0) | |
119 return; | |
120 | |
121 var x = DataProvider.Convert("x", ConvertType.NameToQueryParameter).ToString(); | |
122 var y = DataProvider.Convert("y", ConvertType.NameToQueryParameter).ToString(); | |
123 | |
124 var parms = new List<IDbDataParameter>(x == y ? pq.SqlParameters.Count : parameters.Length); | |
125 | |
126 if (x == y) | |
127 { | |
128 for (var i = 0; i < pq.SqlParameters.Count; i++) | |
129 { | |
130 var sqlp = pq.SqlParameters[i]; | |
131 | |
132 if (sqlp.IsQueryParameter) | |
133 { | |
134 var parm = parameters.Length > i && parameters[i] == sqlp ? parameters[i] : parameters.First(p => p == sqlp); | |
135 AddParameter(parms, x, parm); | |
136 } | |
137 } | |
138 } | |
139 else | |
140 { | |
141 foreach (var parm in parameters) | |
142 { | |
143 if (parm.IsQueryParameter && pq.SqlParameters.Contains(parm)) | |
144 { | |
145 var name = DataProvider.Convert(parm.Name, ConvertType.NameToQueryParameter).ToString(); | |
146 AddParameter(parms, name, parm); | |
147 } | |
148 } | |
149 } | |
150 | |
151 pq.Parameters = parms.ToArray(); | |
152 } | |
153 | |
154 void AddParameter(ICollection<IDbDataParameter> parms, string name, SqlParameter parm) | |
155 { | |
156 var value = MappingSchema.ConvertParameterValue(parm.Value, parm.SystemType); | |
157 | |
158 if (value != null) | |
159 { | |
160 if (parm.DbType == DbType.Object) | |
161 parms.Add(Parameter(name, value)); | |
162 else if (parm.DbSize == 0) | |
163 parms.Add(Parameter(name, value, parm.DbType)); | |
164 else | |
165 parms.Add(Parameter(name, value, parm.DbType, parm.DbSize)); | |
166 } | |
167 else | |
168 { | |
169 var dataType = DataProvider.GetDbType(parm.SystemType); | |
170 if (parm.DbType != DbType.Object) | |
171 dataType = parm.DbType; | |
172 parms.Add(dataType == DbType.Object ? Parameter(name, value) : Parameter(name, null, dataType)); | |
173 } | |
174 } | |
175 | |
176 #endregion | |
177 | |
178 #region ExecuteXXX | |
179 | |
180 int IDataContext.ExecuteNonQuery(object query) | |
181 { | |
182 var pq = (PreparedQuery)query; | |
183 | |
184 SetCommand(pq.Commands[0], pq.Parameters); | |
185 | |
186 var now = default(DateTime); | |
187 | |
188 if (TraceSwitch.TraceInfo) | |
189 now = DateTime.Now; | |
190 | |
191 var n = ExecuteNonQuery(); | |
192 | |
193 if (TraceSwitch.TraceInfo) | |
194 WriteTraceLine(string.Format("Execution time: {0}. Records affected: {1}.\r\n", DateTime.Now - now, n), TraceSwitch.DisplayName); | |
195 | |
196 return n; | |
197 } | |
198 | |
199 object IDataContext.ExecuteScalar(object query) | |
200 { | |
201 var now = default(DateTime); | |
202 | |
203 if (TraceSwitch.TraceInfo) | |
204 now = DateTime.Now; | |
205 | |
206 var ret = ExecuteScalarInternal(query); | |
207 | |
208 if (TraceSwitch.TraceInfo) | |
209 WriteTraceLine(string.Format("Execution time: {0}\r\n", DateTime.Now - now), TraceSwitch.DisplayName); | |
210 | |
211 return ret; | |
212 } | |
213 | |
214 object ExecuteScalarInternal(object query) | |
215 { | |
216 var pq = (PreparedQuery)query; | |
217 | |
218 SetCommand(pq.Commands[0], pq.Parameters); | |
219 | |
220 IDbDataParameter idparam = null; | |
221 | |
222 if ((pq.SqlProvider ?? DataProvider.CreateSqlProvider()).IsIdentityParameterRequired) | |
223 { | |
224 var sql = pq.SqlQuery; | |
225 | |
226 if (sql.IsInsert && sql.Insert.WithIdentity) | |
227 { | |
228 var pname = DataProvider.Convert("IDENTITY_PARAMETER", ConvertType.NameToQueryParameter).ToString(); | |
229 idparam = OutputParameter(pname, DbType.Decimal); | |
230 DataProvider.AttachParameter(Command, idparam); | |
231 } | |
232 } | |
233 | |
234 if (pq.Commands.Length == 1) | |
235 { | |
236 if (idparam != null) | |
237 { | |
238 ExecuteNonQuery(); // так сделано потому, что фаерберд провайдер не возвращает никаких параметров через ExecuteReader | |
239 // остальные провайдеры должны поддерживать такой режим | |
240 return idparam.Value; | |
241 } | |
242 | |
243 return ExecuteScalar(); | |
244 } | |
245 | |
246 ExecuteNonQuery(); | |
247 | |
248 return SetCommand(pq.Commands[1]).ExecuteScalar(); | |
249 } | |
250 | |
251 IDataReader IDataContext.ExecuteReader(object query) | |
252 { | |
253 var pq = (PreparedQuery)query; | |
254 | |
255 SetCommand(pq.Commands[0], pq.Parameters); | |
256 | |
257 var now = default(DateTime); | |
258 | |
259 if (TraceSwitch.TraceInfo) | |
260 now = DateTime.Now; | |
261 | |
262 var ret = ExecuteReader(); | |
263 | |
264 if (TraceSwitch.TraceInfo) | |
265 WriteTraceLine(string.Format("Execution time: {0}\r\n", DateTime.Now - now), TraceSwitch.DisplayName); | |
266 | |
267 return ret; | |
268 } | |
269 | |
270 void IDataContext.ReleaseQuery(object query) | |
271 { | |
272 } | |
273 | |
274 #endregion | |
275 | |
276 #region GetSqlText | |
277 | |
278 string IDataContext.GetSqlText(object query) | |
279 { | |
280 var pq = (PreparedQuery)query; | |
281 | |
282 var sqlProvider = pq.SqlProvider ?? DataProvider.CreateSqlProvider(); | |
283 | |
284 var sb = new StringBuilder(); | |
285 | |
286 sb.Append("-- ").Append(ConfigurationString); | |
287 | |
288 if (ConfigurationString != DataProvider.Name) | |
289 sb.Append(' ').Append(DataProvider.Name); | |
290 | |
291 if (DataProvider.Name != sqlProvider.Name) | |
292 sb.Append(' ').Append(sqlProvider.Name); | |
293 | |
294 sb.AppendLine(); | |
295 | |
296 if (pq.Parameters != null && pq.Parameters.Length > 0) | |
297 { | |
298 foreach (var p in pq.Parameters) | |
299 sb | |
300 .Append("-- DECLARE ") | |
301 .Append(p.ParameterName) | |
302 .Append(' ') | |
303 .Append(p.Value == null ? p.DbType.ToString() : p.Value.GetType().Name) | |
304 .AppendLine(); | |
305 | |
306 sb.AppendLine(); | |
307 | |
308 foreach (var p in pq.Parameters) | |
309 { | |
310 var value = p.Value; | |
311 | |
312 if (value is string || value is char) | |
313 value = "'" + value.ToString().Replace("'", "''") + "'"; | |
314 | |
315 sb | |
316 .Append("-- SET ") | |
317 .Append(p.ParameterName) | |
318 .Append(" = ") | |
319 .Append(value) | |
320 .AppendLine(); | |
321 } | |
322 | |
323 sb.AppendLine(); | |
324 } | |
325 | |
326 foreach (var command in pq.Commands) | |
327 sb.AppendLine(command); | |
328 | |
329 while (sb[sb.Length - 1] == '\n' || sb[sb.Length - 1] == '\r') | |
330 sb.Length--; | |
331 | |
332 sb.AppendLine(); | |
333 | |
334 return sb.ToString(); | |
335 } | |
336 | |
337 #endregion | |
338 | |
339 #region IDataContext Members | |
340 | |
341 IDataContext IDataContext.Clone(bool forNestedQuery) | |
342 { | |
343 if (forNestedQuery && _connection != null && IsMarsEnabled) | |
344 return new DbManager(_dataProvider, _connection) { _mappingSchema = _mappingSchema, _transaction = _transaction }; | |
345 | |
346 return Clone(); | |
347 } | |
348 | |
349 string IDataContext.ContextID | |
350 { | |
351 get { return DataProvider.Name; } | |
352 } | |
353 | |
354 static Func<ISqlProvider> GetCreateSqlProvider(DataProviderBase dp) | |
355 { | |
356 return dp.CreateSqlProvider; | |
357 } | |
358 | |
359 Func<ISqlProvider> IDataContext.CreateSqlProvider | |
360 { | |
361 get { return GetCreateSqlProvider(DataProvider); } | |
362 } | |
363 | |
364 #endregion | |
365 } | |
366 } |