Mercurial > pub > bltoolkit
diff Source/ServiceModel/LinqService.cs @ 0:f990fcb411a9
Копия текущей версии из github
author | cin |
---|---|
date | Thu, 27 Mar 2014 21:46:09 +0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Source/ServiceModel/LinqService.cs Thu Mar 27 21:46:09 2014 +0400 @@ -0,0 +1,272 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.ServiceModel; +using System.Web.Services; + +namespace BLToolkit.ServiceModel +{ + using Data; + using Data.Linq; + using Data.Sql; + + [ServiceBehavior (InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)] + [WebService (Namespace = "http://tempuri.org/")] + [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] + public class LinqService : ILinqService + { + public LinqService() + { + } + + public LinqService(string configuration) + { + Configuration = configuration; + } + + public string Configuration { get; set; } + public bool AllowUpdates { get; set; } + + public static Func<string,Type> TypeResolver = _ => null; + + public virtual IDataContext CreateDataContext() + { + return Settings.CreateDefaultDataContext(Configuration); + } + + protected virtual void ValidateQuery(LinqServiceQuery query) + { + if (AllowUpdates == false && !query.Query.IsSelect) + throw new LinqException("Insert/Update/Delete requests are not allowed by the service policy."); + } + + protected virtual void HandleException(Exception exception) + { + } + + #region ILinqService Members + + public Type SqlProviderType { get; set; } + + [WebMethod] + public virtual string GetSqlProviderType() + { + try + { + if (SqlProviderType == null) + using (var ctx = CreateDataContext()) + SqlProviderType = ctx.CreateSqlProvider().GetType(); + + return SqlProviderType.FullName; + } + catch (Exception exception) + { + HandleException(exception); + throw; + } + } + + class QueryContext : IQueryContext + { + public SqlQuery SqlQuery { get; set; } + public object Context { get; set; } + public SqlParameter[] Parameters { get; set; } + + public SqlParameter[] GetParameters() + { + return Parameters; + } + } + + [WebMethod] + public int ExecuteNonQuery(string queryData) + { + try + { + var query = LinqServiceSerializer.Deserialize(queryData); + + ValidateQuery(query); + + using (var db = CreateDataContext()) + { + var obj = db.SetQuery(new QueryContext { SqlQuery = query.Query, Parameters = query.Parameters }); + return db.ExecuteNonQuery(obj); + } + } + catch (Exception exception) + { + HandleException(exception); + throw; + } + } + + [WebMethod] + public object ExecuteScalar(string queryData) + { + try + { + var query = LinqServiceSerializer.Deserialize(queryData); + + ValidateQuery(query); + + using (var db = CreateDataContext()) + { + var obj = db.SetQuery(new QueryContext { SqlQuery = query.Query, Parameters = query.Parameters }); + return db.ExecuteScalar(obj); + } + } + catch (Exception exception) + { + HandleException(exception); + throw; + } + } + + [WebMethod] + public string ExecuteReader(string queryData) + { + try + { + var query = LinqServiceSerializer.Deserialize(queryData); + + ValidateQuery(query); + + using (var db = CreateDataContext()) + { + var obj = db.SetQuery(new QueryContext { SqlQuery = query.Query, Parameters = query.Parameters }); + + using (var rd = db.ExecuteReader(obj)) + { + var ret = new LinqServiceResult + { + QueryID = Guid.NewGuid(), + FieldCount = rd.FieldCount, + FieldNames = new string[rd.FieldCount], + FieldTypes = new Type [rd.FieldCount], + Data = new List<string[]>(), + }; + + for (var i = 0; i < ret.FieldCount; i++) + { + ret.FieldNames[i] = rd.GetName(i); + ret.FieldTypes[i] = rd.GetFieldType(i); + } + + var varyingTypes = new List<Type>(); + + while (rd.Read()) + { + var data = new string [rd.FieldCount]; + var codes = new TypeCode[rd.FieldCount]; + + for (var i = 0; i < ret.FieldCount; i++) + codes[i] = Type.GetTypeCode(ret.FieldTypes[i]); + + ret.RowCount++; + + for (var i = 0; i < ret.FieldCount; i++) + { + if (!rd.IsDBNull(i)) + { + var code = codes[i]; + var type = rd.GetFieldType(i); + var idx = -1; + + if (type != ret.FieldTypes[i]) + { + code = Type.GetTypeCode(type); + idx = varyingTypes.IndexOf(type); + + if (idx < 0) + { + varyingTypes.Add(type); + idx = varyingTypes.Count - 1; + } + } + + switch (code) + { + case TypeCode.Decimal : data[i] = rd.GetDecimal (i).ToString(CultureInfo.InvariantCulture); break; + case TypeCode.Double : data[i] = rd.GetDouble (i).ToString(CultureInfo.InvariantCulture); break; + case TypeCode.Single : data[i] = rd.GetFloat (i).ToString(CultureInfo.InvariantCulture); break; + case TypeCode.DateTime : data[i] = rd.GetDateTime(i).ToString("o"); break; + default : + { + if (type == typeof(DateTimeOffset)) + { + var dt = rd.GetValue(i); + + if (dt is DateTime) + data[i] = ((DateTime)dt).ToString("o"); + else if (dt is DateTimeOffset) + data[i] = ((DateTimeOffset)dt).ToString("o"); + else + data[i] = rd.GetValue(i).ToString(); + } + else if (ret.FieldTypes[i] == typeof(byte[])) + data[i] = Convert.ToBase64String((byte[])rd.GetValue(i)); + else + data[i] = (rd.GetValue(i) ?? "").ToString(); + + break; + } + } + + if (idx >= 0) + data[i] = "\0" + (char)idx + data[i]; + } + } + + ret.Data.Add(data); + } + + ret.VaryingTypes = varyingTypes.ToArray(); + + return LinqServiceSerializer.Serialize(ret); + } + } + } + catch (Exception exception) + { + HandleException(exception); + throw; + } + } + + [WebMethod] + public int ExecuteBatch(string queryData) + { + try + { + var data = LinqServiceSerializer.DeserializeStringArray(queryData); + var queries = data.Select<string,LinqServiceQuery>(LinqServiceSerializer.Deserialize).ToArray(); + + foreach (var query in queries) + ValidateQuery(query); + + using (var db = CreateDataContext()) + { + if (db is DbManager) ((DbManager)db).BeginTransaction(); + + foreach (var query in queries) + { + var obj = db.SetQuery(new QueryContext { SqlQuery = query.Query, Parameters = query.Parameters }); + db.ExecuteNonQuery(obj); + } + + if (db is DbManager) ((DbManager)db).CommitTransaction(); + + return queryData.Length; + } + } + catch (Exception exception) + { + HandleException(exception); + throw; + } + } + + #endregion + } +}