0
|
1 using System;
|
|
2 using System.Collections.Generic;
|
|
3 using System.Globalization;
|
|
4 using System.Linq;
|
|
5 using System.ServiceModel;
|
|
6 using System.Web.Services;
|
|
7
|
|
8 namespace BLToolkit.ServiceModel
|
|
9 {
|
|
10 using Data;
|
|
11 using Data.Linq;
|
|
12 using Data.Sql;
|
|
13
|
|
14 [ServiceBehavior (InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
|
|
15 [WebService (Namespace = "http://tempuri.org/")]
|
|
16 [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
|
|
17 public class LinqService : ILinqService
|
|
18 {
|
|
19 public LinqService()
|
|
20 {
|
|
21 }
|
|
22
|
|
23 public LinqService(string configuration)
|
|
24 {
|
|
25 Configuration = configuration;
|
|
26 }
|
|
27
|
|
28 public string Configuration { get; set; }
|
|
29 public bool AllowUpdates { get; set; }
|
|
30
|
|
31 public static Func<string,Type> TypeResolver = _ => null;
|
|
32
|
|
33 public virtual IDataContext CreateDataContext()
|
|
34 {
|
|
35 return Settings.CreateDefaultDataContext(Configuration);
|
|
36 }
|
|
37
|
|
38 protected virtual void ValidateQuery(LinqServiceQuery query)
|
|
39 {
|
|
40 if (AllowUpdates == false && !query.Query.IsSelect)
|
|
41 throw new LinqException("Insert/Update/Delete requests are not allowed by the service policy.");
|
|
42 }
|
|
43
|
|
44 protected virtual void HandleException(Exception exception)
|
|
45 {
|
|
46 }
|
|
47
|
|
48 #region ILinqService Members
|
|
49
|
|
50 public Type SqlProviderType { get; set; }
|
|
51
|
|
52 [WebMethod]
|
|
53 public virtual string GetSqlProviderType()
|
|
54 {
|
|
55 try
|
|
56 {
|
|
57 if (SqlProviderType == null)
|
|
58 using (var ctx = CreateDataContext())
|
|
59 SqlProviderType = ctx.CreateSqlProvider().GetType();
|
|
60
|
|
61 return SqlProviderType.FullName;
|
|
62 }
|
|
63 catch (Exception exception)
|
|
64 {
|
|
65 HandleException(exception);
|
|
66 throw;
|
|
67 }
|
|
68 }
|
|
69
|
|
70 class QueryContext : IQueryContext
|
|
71 {
|
|
72 public SqlQuery SqlQuery { get; set; }
|
|
73 public object Context { get; set; }
|
|
74 public SqlParameter[] Parameters { get; set; }
|
|
75
|
|
76 public SqlParameter[] GetParameters()
|
|
77 {
|
|
78 return Parameters;
|
|
79 }
|
|
80 }
|
|
81
|
|
82 [WebMethod]
|
|
83 public int ExecuteNonQuery(string queryData)
|
|
84 {
|
|
85 try
|
|
86 {
|
|
87 var query = LinqServiceSerializer.Deserialize(queryData);
|
|
88
|
|
89 ValidateQuery(query);
|
|
90
|
|
91 using (var db = CreateDataContext())
|
|
92 {
|
|
93 var obj = db.SetQuery(new QueryContext { SqlQuery = query.Query, Parameters = query.Parameters });
|
|
94 return db.ExecuteNonQuery(obj);
|
|
95 }
|
|
96 }
|
|
97 catch (Exception exception)
|
|
98 {
|
|
99 HandleException(exception);
|
|
100 throw;
|
|
101 }
|
|
102 }
|
|
103
|
|
104 [WebMethod]
|
|
105 public object ExecuteScalar(string queryData)
|
|
106 {
|
|
107 try
|
|
108 {
|
|
109 var query = LinqServiceSerializer.Deserialize(queryData);
|
|
110
|
|
111 ValidateQuery(query);
|
|
112
|
|
113 using (var db = CreateDataContext())
|
|
114 {
|
|
115 var obj = db.SetQuery(new QueryContext { SqlQuery = query.Query, Parameters = query.Parameters });
|
|
116 return db.ExecuteScalar(obj);
|
|
117 }
|
|
118 }
|
|
119 catch (Exception exception)
|
|
120 {
|
|
121 HandleException(exception);
|
|
122 throw;
|
|
123 }
|
|
124 }
|
|
125
|
|
126 [WebMethod]
|
|
127 public string ExecuteReader(string queryData)
|
|
128 {
|
|
129 try
|
|
130 {
|
|
131 var query = LinqServiceSerializer.Deserialize(queryData);
|
|
132
|
|
133 ValidateQuery(query);
|
|
134
|
|
135 using (var db = CreateDataContext())
|
|
136 {
|
|
137 var obj = db.SetQuery(new QueryContext { SqlQuery = query.Query, Parameters = query.Parameters });
|
|
138
|
|
139 using (var rd = db.ExecuteReader(obj))
|
|
140 {
|
|
141 var ret = new LinqServiceResult
|
|
142 {
|
|
143 QueryID = Guid.NewGuid(),
|
|
144 FieldCount = rd.FieldCount,
|
|
145 FieldNames = new string[rd.FieldCount],
|
|
146 FieldTypes = new Type [rd.FieldCount],
|
|
147 Data = new List<string[]>(),
|
|
148 };
|
|
149
|
|
150 for (var i = 0; i < ret.FieldCount; i++)
|
|
151 {
|
|
152 ret.FieldNames[i] = rd.GetName(i);
|
|
153 ret.FieldTypes[i] = rd.GetFieldType(i);
|
|
154 }
|
|
155
|
|
156 var varyingTypes = new List<Type>();
|
|
157
|
|
158 while (rd.Read())
|
|
159 {
|
|
160 var data = new string [rd.FieldCount];
|
|
161 var codes = new TypeCode[rd.FieldCount];
|
|
162
|
|
163 for (var i = 0; i < ret.FieldCount; i++)
|
|
164 codes[i] = Type.GetTypeCode(ret.FieldTypes[i]);
|
|
165
|
|
166 ret.RowCount++;
|
|
167
|
|
168 for (var i = 0; i < ret.FieldCount; i++)
|
|
169 {
|
|
170 if (!rd.IsDBNull(i))
|
|
171 {
|
|
172 var code = codes[i];
|
|
173 var type = rd.GetFieldType(i);
|
|
174 var idx = -1;
|
|
175
|
|
176 if (type != ret.FieldTypes[i])
|
|
177 {
|
|
178 code = Type.GetTypeCode(type);
|
|
179 idx = varyingTypes.IndexOf(type);
|
|
180
|
|
181 if (idx < 0)
|
|
182 {
|
|
183 varyingTypes.Add(type);
|
|
184 idx = varyingTypes.Count - 1;
|
|
185 }
|
|
186 }
|
|
187
|
|
188 switch (code)
|
|
189 {
|
|
190 case TypeCode.Decimal : data[i] = rd.GetDecimal (i).ToString(CultureInfo.InvariantCulture); break;
|
|
191 case TypeCode.Double : data[i] = rd.GetDouble (i).ToString(CultureInfo.InvariantCulture); break;
|
|
192 case TypeCode.Single : data[i] = rd.GetFloat (i).ToString(CultureInfo.InvariantCulture); break;
|
|
193 case TypeCode.DateTime : data[i] = rd.GetDateTime(i).ToString("o"); break;
|
|
194 default :
|
|
195 {
|
|
196 if (type == typeof(DateTimeOffset))
|
|
197 {
|
|
198 var dt = rd.GetValue(i);
|
|
199
|
|
200 if (dt is DateTime)
|
|
201 data[i] = ((DateTime)dt).ToString("o");
|
|
202 else if (dt is DateTimeOffset)
|
|
203 data[i] = ((DateTimeOffset)dt).ToString("o");
|
|
204 else
|
|
205 data[i] = rd.GetValue(i).ToString();
|
|
206 }
|
|
207 else if (ret.FieldTypes[i] == typeof(byte[]))
|
|
208 data[i] = Convert.ToBase64String((byte[])rd.GetValue(i));
|
|
209 else
|
|
210 data[i] = (rd.GetValue(i) ?? "").ToString();
|
|
211
|
|
212 break;
|
|
213 }
|
|
214 }
|
|
215
|
|
216 if (idx >= 0)
|
|
217 data[i] = "\0" + (char)idx + data[i];
|
|
218 }
|
|
219 }
|
|
220
|
|
221 ret.Data.Add(data);
|
|
222 }
|
|
223
|
|
224 ret.VaryingTypes = varyingTypes.ToArray();
|
|
225
|
|
226 return LinqServiceSerializer.Serialize(ret);
|
|
227 }
|
|
228 }
|
|
229 }
|
|
230 catch (Exception exception)
|
|
231 {
|
|
232 HandleException(exception);
|
|
233 throw;
|
|
234 }
|
|
235 }
|
|
236
|
|
237 [WebMethod]
|
|
238 public int ExecuteBatch(string queryData)
|
|
239 {
|
|
240 try
|
|
241 {
|
|
242 var data = LinqServiceSerializer.DeserializeStringArray(queryData);
|
|
243 var queries = data.Select<string,LinqServiceQuery>(LinqServiceSerializer.Deserialize).ToArray();
|
|
244
|
|
245 foreach (var query in queries)
|
|
246 ValidateQuery(query);
|
|
247
|
|
248 using (var db = CreateDataContext())
|
|
249 {
|
|
250 if (db is DbManager) ((DbManager)db).BeginTransaction();
|
|
251
|
|
252 foreach (var query in queries)
|
|
253 {
|
|
254 var obj = db.SetQuery(new QueryContext { SqlQuery = query.Query, Parameters = query.Parameters });
|
|
255 db.ExecuteNonQuery(obj);
|
|
256 }
|
|
257
|
|
258 if (db is DbManager) ((DbManager)db).CommitTransaction();
|
|
259
|
|
260 return queryData.Length;
|
|
261 }
|
|
262 }
|
|
263 catch (Exception exception)
|
|
264 {
|
|
265 HandleException(exception);
|
|
266 throw;
|
|
267 }
|
|
268 }
|
|
269
|
|
270 #endregion
|
|
271 }
|
|
272 }
|