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