comparison Source/ServiceModel/RemoteDataContextBase.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.Expressions;
5 using System.Text;
6
7 namespace BLToolkit.ServiceModel
8 {
9 using Data.Linq;
10 using Data.Sql.SqlProvider;
11 using Mapping;
12
13 public abstract class RemoteDataContextBase : IDataContext
14 {
15 protected abstract ILinqService GetClient();
16 protected abstract IDataContext Clone ();
17 protected abstract string ContextIDPrefix { get; }
18
19 string _contextID;
20 string IDataContext.ContextID
21 {
22 get { return _contextID ?? (_contextID = ContextIDPrefix + SqlProviderType.Name.Replace("SqlProvider", "")); }
23 }
24
25 private MappingSchema _mappingSchema;
26 public MappingSchema MappingSchema
27 {
28 get
29 {
30 if (_mappingSchema == null)
31 {
32 var sp = ((IDataContext)this).CreateSqlProvider();
33 _mappingSchema = sp is IMappingSchemaProvider ? ((IMappingSchemaProvider)sp).MappingSchema : Map.DefaultSchema;
34 }
35
36 return _mappingSchema;
37 }
38
39 set { _mappingSchema = value; }
40 }
41
42 private Type _sqlProviderType;
43 public virtual Type SqlProviderType
44 {
45 get
46 {
47 if (_sqlProviderType == null)
48 {
49 var client = GetClient();
50
51 try
52 {
53 var type = client.GetSqlProviderType();
54 _sqlProviderType = Type.GetType(type);
55 }
56 finally
57 {
58 ((IDisposable)client).Dispose();
59 }
60 }
61
62 return _sqlProviderType;
63 }
64
65 set { _sqlProviderType = value; }
66 }
67
68 public bool IsMarsEnabled
69 {
70 get { return false; }
71 }
72
73 static readonly Dictionary<Type,Func<ISqlProvider>> _sqlProviders = new Dictionary<Type, Func<ISqlProvider>>();
74
75 Func<ISqlProvider> _createSqlProvider;
76
77 Func<ISqlProvider> IDataContext.CreateSqlProvider
78 {
79 get
80 {
81 if (_createSqlProvider == null)
82 {
83 var type = SqlProviderType;
84
85 if (!_sqlProviders.TryGetValue(type, out _createSqlProvider))
86 lock (_sqlProviderType)
87 if (!_sqlProviders.TryGetValue(type, out _createSqlProvider))
88 _sqlProviders.Add(type, _createSqlProvider = Expression.Lambda<Func<ISqlProvider>>(Expression.New(type)).Compile());
89 }
90
91 return _createSqlProvider;
92 }
93 }
94
95 List<string> _queryBatch;
96 int _batchCounter;
97
98 public void BeginBatch()
99 {
100 _batchCounter++;
101
102 if (_queryBatch == null)
103 _queryBatch = new List<string>();
104 }
105
106 public void CommitBatch()
107 {
108 if (_batchCounter == 0)
109 throw new InvalidOperationException();
110
111 _batchCounter--;
112
113 if (_batchCounter == 0)
114 {
115 var client = GetClient();
116
117 try
118 {
119 var data = LinqServiceSerializer.Serialize(_queryBatch.ToArray());
120 client.ExecuteBatch(data);
121 }
122 finally
123 {
124 ((IDisposable)client).Dispose();
125 _queryBatch = null;
126 }
127 }
128 }
129
130 class QueryContext
131 {
132 public IQueryContext Query;
133 public ILinqService Client;
134 }
135
136 object IDataContext.SetQuery(IQueryContext queryContext)
137 {
138 return new QueryContext { Query = queryContext };
139 }
140
141 int IDataContext.ExecuteNonQuery(object query)
142 {
143 var ctx = (QueryContext)query;
144 var q = ctx.Query.SqlQuery.ProcessParameters();
145 var data = LinqServiceSerializer.Serialize(q, q.IsParameterDependent ? q.Parameters.ToArray() : ctx.Query.GetParameters());
146
147 if (_batchCounter > 0)
148 {
149 _queryBatch.Add(data);
150 return -1;
151 }
152
153 ctx.Client = GetClient();
154
155 return ctx.Client.ExecuteNonQuery(data);
156 }
157
158 object IDataContext.ExecuteScalar(object query)
159 {
160 if (_batchCounter > 0)
161 throw new LinqException("Incompatible batch operation.");
162
163 var ctx = (QueryContext)query;
164
165 ctx.Client = GetClient();
166
167 var q = ctx.Query.SqlQuery.ProcessParameters();
168
169 return ctx.Client.ExecuteScalar(
170 LinqServiceSerializer.Serialize(q, q.IsParameterDependent ? q.Parameters.ToArray() : ctx.Query.GetParameters()));
171 }
172
173 IDataReader IDataContext.ExecuteReader(object query)
174 {
175 if (_batchCounter > 0)
176 throw new LinqException("Incompatible batch operation.");
177
178 var ctx = (QueryContext)query;
179
180 ctx.Client = GetClient();
181
182 var q = ctx.Query.SqlQuery.ProcessParameters();
183 var ret = ctx.Client.ExecuteReader(
184 LinqServiceSerializer.Serialize(q, q.IsParameterDependent ? q.Parameters.ToArray() : ctx.Query.GetParameters()));
185 var result = LinqServiceSerializer.DeserializeResult(ret);
186
187 return new ServiceModelDataReader(result);
188 }
189
190 public void ReleaseQuery(object query)
191 {
192 var ctx = (QueryContext)query;
193
194 if (ctx.Client != null)
195 ((IDisposable)ctx.Client).Dispose();
196 }
197
198 string IDataContext.GetSqlText(object query)
199 {
200 var ctx = (QueryContext)query;
201 var sqlProvider = ((IDataContext)this).CreateSqlProvider();
202 var sb = new StringBuilder();
203
204 sb
205 .Append("-- ")
206 .Append("ServiceModel")
207 .Append(' ')
208 .Append(((IDataContext)this).ContextID)
209 .Append(' ')
210 .Append(sqlProvider.Name)
211 .AppendLine();
212
213 if (ctx.Query.SqlQuery.Parameters != null && ctx.Query.SqlQuery.Parameters.Count > 0)
214 {
215 foreach (var p in ctx.Query.SqlQuery.Parameters)
216 sb
217 .Append("-- DECLARE ")
218 .Append(p.Name)
219 .Append(' ')
220 .Append(p.Value == null ? p.SystemType.ToString() : p.Value.GetType().Name)
221 .AppendLine();
222
223 sb.AppendLine();
224
225 foreach (var p in ctx.Query.SqlQuery.Parameters)
226 {
227 var value = p.Value;
228
229 if (value is string || value is char)
230 value = "'" + value.ToString().Replace("'", "''") + "'";
231
232 sb
233 .Append("-- SET ")
234 .Append(p.Name)
235 .Append(" = ")
236 .Append(value)
237 .AppendLine();
238 }
239
240 sb.AppendLine();
241 }
242
243 var cc = sqlProvider.CommandCount(ctx.Query.SqlQuery);
244 var commands = new string[cc];
245
246 for (var i = 0; i < cc; i++)
247 {
248 sb.Length = 0;
249
250 sqlProvider.BuildSql(i, ctx.Query.SqlQuery, sb, 0, 0, false);
251 commands[i] = sb.ToString();
252 }
253
254 if (!ctx.Query.SqlQuery.IsParameterDependent)
255 ctx.Query.Context = commands;
256
257 foreach (var command in commands)
258 sb.AppendLine(command);
259
260 return sb.ToString();
261 }
262
263 IDataContext IDataContext.Clone(bool forNestedQuery)
264 {
265 return Clone();
266 }
267
268 public event EventHandler OnClosing;
269
270 public void Dispose()
271 {
272 if (OnClosing != null)
273 OnClosing(this, EventArgs.Empty);
274 }
275 }
276 }