diff Source/DataAccess/SqlQueryBase.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/DataAccess/SqlQueryBase.cs	Thu Mar 27 21:46:09 2014 +0400
@@ -0,0 +1,384 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Text;
+
+using BLToolkit.Aspects;
+using BLToolkit.Data;
+using BLToolkit.Data.DataProvider;
+using BLToolkit.Mapping;
+using BLToolkit.Reflection;
+using BLToolkit.Reflection.Extension;
+
+namespace BLToolkit.DataAccess
+{
+	public abstract class SqlQueryBase : DataAccessorBase
+	{
+		#region Constructors
+
+		protected SqlQueryBase()
+		{
+		}
+
+		protected SqlQueryBase(DbManager dbManager)
+			: base(dbManager)
+		{
+		}
+
+		protected SqlQueryBase(DbManager dbManager, bool dispose)
+			: base(dbManager, dispose)
+		{
+		}
+
+		#endregion
+
+		#region Protected Members
+
+		[NoInterception]
+		protected virtual MemberMapper[] GetFieldList(ObjectMapper om)
+		{
+			var list = new List<MemberMapper>(om.Count);
+
+			foreach (MemberMapper mm in om)
+				if (mm.MapMemberInfo.SqlIgnore == false)
+					list.Add(mm);
+
+			return list.ToArray();
+		}
+
+		[NoInterception]
+		protected virtual MemberMapper[] GetNonKeyFieldList(ObjectMapper om)
+		{
+			var typeExt = TypeExtension.GetTypeExtension(om.TypeAccessor.OriginalType, Extensions);
+			var list    = new List<MemberMapper>();
+
+			foreach (MemberMapper mm in om)
+			{
+				if (mm.MapMemberInfo.SqlIgnore)
+					continue;
+
+				var ma = mm.MapMemberInfo.MemberAccessor;
+
+				bool isSet;
+				MappingSchema.MetadataProvider.GetPrimaryKeyOrder(om.TypeAccessor.OriginalType, typeExt, ma, out isSet);
+
+				if (!isSet)
+					list.Add(mm);
+			}
+
+			return list.ToArray();
+		}
+
+		struct MemberOrder
+		{
+			public MemberOrder(MemberMapper memberMapper, int order)
+			{
+				MemberMapper = memberMapper;
+				Order        = order;
+			}
+
+			public readonly MemberMapper MemberMapper;
+			public readonly int          Order;
+		}
+
+		private static readonly Hashtable _keyList = new Hashtable();
+
+		[NoInterception]
+		protected internal virtual MemberMapper[] GetKeyFieldList(DbManager db, Type type)
+		{
+			var key    = type.FullName + "$" + db.DataProvider.UniqueName;
+			var mmList = (MemberMapper[])_keyList[key];
+
+			if (mmList == null)
+			{
+				var typeExt = TypeExtension.GetTypeExtension(type, Extensions);
+				var list    = new List<MemberOrder>();
+
+				foreach (MemberMapper mm in db.MappingSchema.GetObjectMapper(type))
+				{
+					if (mm.MapMemberInfo.SqlIgnore)
+						continue;
+
+					var ma = mm.MapMemberInfo.MemberAccessor;
+
+					if (TypeHelper.IsScalar(ma.Type))
+					{
+						bool isSet;
+						var order = MappingSchema.MetadataProvider.GetPrimaryKeyOrder(type, typeExt, ma, out isSet);
+
+						if (isSet)
+							list.Add(new MemberOrder(mm, order));
+					}
+				}
+
+				list.Sort((x, y) => x.Order - y.Order);
+
+				_keyList[key] = mmList = new MemberMapper[list.Count];
+
+				for (var i = 0; i < list.Count; i++)
+					mmList[i] = list[i].MemberMapper;
+			}
+
+			return mmList;
+		}
+
+		[NoInterception]
+		protected virtual void AddWherePK(DbManager db, SqlQueryInfo query, StringBuilder sb, int nParameter)
+		{
+			sb.Append("WHERE\n");
+
+			var memberMappers = GetKeyFieldList(db, query.ObjectType);
+
+			if (memberMappers.Length == 0)
+				throw new DataAccessException(
+						string.Format("No primary key field(s) in the type '{0}'.", query.ObjectType.FullName));
+
+			foreach (var mm in memberMappers)
+			{
+				var p = query.AddParameter(
+					db.DataProvider.Convert(mm.Name + "_W", ConvertType.NameToQueryParameter).ToString(),
+					mm.Name);
+
+				sb.AppendFormat("\t{0} = ", db.DataProvider.Convert(p.FieldName, ConvertType.NameToQueryField));
+
+				if (nParameter < 0)
+					sb.AppendFormat("{0} AND\n", p.ParameterName);
+				else
+					sb.AppendFormat("{{{0}}} AND\n", nParameter++);
+			}
+
+			sb.Remove(sb.Length - 5, 5);
+		}
+
+		protected SqlQueryInfo CreateSelectByKeySqlText(DbManager db, Type type)
+		{
+			var om    = db.MappingSchema.GetObjectMapper(type);
+			var sb    = new StringBuilder();
+			var query = new SqlQueryInfo(om);
+
+			sb.Append("SELECT\n");
+
+			foreach (var mm in GetFieldList(om))
+				sb.AppendFormat("\t{0},\n",
+					db.DataProvider.Convert(mm.Name, ConvertType.NameToQueryField));
+
+			sb.Remove(sb.Length - 2, 1);
+
+			sb.Append("FROM\n\t");
+
+			AppendTableName(sb, db, type);
+
+			AddWherePK(db, query, sb, -1);
+
+			query.QueryText = sb.ToString();
+
+			return query;
+		}
+
+		// NOTE changed to virtual
+		protected virtual void AppendTableName(StringBuilder sb, DbManager db, Type type)
+		{
+			var database = GetDatabaseName(type);
+			var owner    = GetOwnerName   (type);
+			var name     = GetTableName   (type);
+
+			db.DataProvider.CreateSqlProvider().BuildTableName(sb,
+				database == null ? null : db.DataProvider.Convert(database, ConvertType.NameToDatabase).  ToString(),
+				owner    == null ? null : db.DataProvider.Convert(owner,    ConvertType.NameToOwner).     ToString(),
+				name     == null ? null : db.DataProvider.Convert(name,     ConvertType.NameToQueryTable).ToString());
+
+			sb.AppendLine();
+		}
+
+		protected SqlQueryInfo CreateSelectAllSqlText(DbManager db, Type type)
+		{
+			var om    = db.MappingSchema.GetObjectMapper(type);
+			var sb    = new StringBuilder();
+			var query = new SqlQueryInfo(om);
+
+			sb.Append("SELECT\n");
+
+			foreach (var mm in GetFieldList(om))
+				sb.AppendFormat("\t{0},\n",
+					db.DataProvider.Convert(mm.Name, ConvertType.NameToQueryField));
+
+			sb.Remove(sb.Length - 2, 1);
+
+			sb.Append("FROM\n\t");
+			AppendTableName(sb, db, type);
+
+			query.QueryText = sb.ToString();
+
+			return query;
+		}
+
+		protected SqlQueryInfo CreateInsertSqlText(DbManager db, Type type, int nParameter)
+		{
+			var typeExt = TypeExtension.GetTypeExtension(type, Extensions);
+			var om      = db.MappingSchema.GetObjectMapper(type);
+			var list    = new List<MemberMapper>();
+			var sb      = new StringBuilder();
+			var query   = new SqlQueryInfo(om);
+			var mp      = MappingSchema.MetadataProvider;
+
+			sb.Append("INSERT INTO ");
+			AppendTableName(sb, db, type);
+			sb.Append(" (\n");
+
+			foreach (var mm in GetFieldList(om))
+			{
+				// IT: This works incorrectly for complex mappers.
+				//
+				// [2009-03-24] ili: use mm.MemberAccessor instead of mm.ComplexMemberAccessor
+				// as in CreateUpdateSqlText
+				//
+
+				bool isSet;
+				var nonUpdatableAttribute = mp.GetNonUpdatableAttribute(type, typeExt, mm.MapMemberInfo.MemberAccessor, out isSet);
+
+				if (nonUpdatableAttribute == null || !isSet || nonUpdatableAttribute.OnInsert == false)
+				{
+					sb.AppendFormat("\t{0},\n",
+						db.DataProvider.Convert(mm.Name, ConvertType.NameToQueryField));
+					list.Add(mm);
+				}
+			}
+
+			sb.Remove(sb.Length - 2, 1);
+
+			sb.Append(") VALUES (\n");
+
+			foreach (var mm in list)
+			{
+				var p = query.AddParameter(
+					db.DataProvider.Convert(mm.Name + "_P", ConvertType.NameToQueryParameter).ToString(),
+					mm.Name);
+
+				if (nParameter < 0)
+					sb.AppendFormat("\t{0},\n", p.ParameterName);
+					//sb.AppendFormat("\t{0},\n", db.DataProvider.Convert(p.ParameterName, ConvertType.NameToQueryParameter));
+				else
+					sb.AppendFormat("\t{{{0}}},\n", nParameter++);
+			}
+
+			sb.Remove(sb.Length - 2, 1);
+
+			sb.Append(")");
+
+			query.QueryText = sb.ToString();
+
+			return query;
+		}
+
+		protected SqlQueryInfo CreateUpdateSqlText(DbManager db, Type type, int nParameter)
+		{
+			var typeExt = TypeExtension.GetTypeExtension(type, Extensions);
+			var om      = db.MappingSchema.GetObjectMapper(type);
+			var sb      = new StringBuilder();
+			var query   = new SqlQueryInfo(om);
+			var mp      = MappingSchema.MetadataProvider;
+
+			sb.Append("UPDATE\n\t");
+			AppendTableName(sb, db, type);
+			sb.Append("\nSET\n");
+
+			var fields    = GetFieldList(om);
+			var hasFields = false;
+
+			foreach (var mm in fields)
+			{
+				bool isSet;
+
+				var nonUpdatableAttribute = mp.GetNonUpdatableAttribute(type, typeExt, mm.MapMemberInfo.MemberAccessor, out isSet);
+
+				if (nonUpdatableAttribute != null && isSet && nonUpdatableAttribute.OnUpdate == true)
+					continue;
+
+				mp.GetPrimaryKeyOrder(type, typeExt, mm.MapMemberInfo.MemberAccessor, out isSet);
+
+				if (isSet)
+					continue;
+
+				hasFields = true;
+
+				var p = query.AddParameter(
+					db.DataProvider.Convert(mm.Name + "_P", ConvertType.NameToQueryParameter).ToString(),
+					mm.Name);
+
+				sb.AppendFormat("\t{0} = ", db.DataProvider.Convert(p.FieldName, ConvertType.NameToQueryField));
+
+				if (nParameter < 0)
+					sb.AppendFormat("{0},\n", p.ParameterName);
+				else
+					sb.AppendFormat("\t{{{0}}},\n", nParameter++);
+			}
+
+			if (!hasFields)
+				throw new DataAccessException(
+						string.Format("There are no fields to update in the type '{0}'.", query.ObjectType.FullName));
+
+			sb.Remove(sb.Length - 2, 1);
+
+			AddWherePK(db, query, sb, nParameter);
+
+			query.QueryText = sb.ToString();
+
+			return query;
+		}
+
+		protected SqlQueryInfo CreateDeleteSqlText(DbManager db, Type type, int nParameter)
+		{
+			var om    = db.MappingSchema.GetObjectMapper(type);
+			var sb    = new StringBuilder();
+			var query = new SqlQueryInfo(om);
+
+			sb.Append("DELETE FROM\n\t");
+			AppendTableName(sb, db, type);
+			sb.AppendLine();
+
+			AddWherePK(db, query, sb, nParameter);
+
+			query.QueryText = sb.ToString();
+
+			return query;
+		}
+
+		[NoInterception]
+		protected virtual SqlQueryInfo CreateSqlText(DbManager db, Type type, string actionName)
+		{
+			switch (actionName)
+			{
+				case "SelectByKey": return CreateSelectByKeySqlText(db, type);
+				case "SelectAll":   return CreateSelectAllSqlText  (db, type);
+				case "Insert":      return CreateInsertSqlText     (db, type, -1);
+				case "InsertBatch": return CreateInsertSqlText     (db, type,  0);
+				case "Update":      return CreateUpdateSqlText     (db, type, -1);
+				case "UpdateBatch": return CreateUpdateSqlText     (db, type,  0);
+				case "Delete":      return CreateDeleteSqlText     (db, type, -1);
+				case "DeleteBatch": return CreateDeleteSqlText     (db, type,  0);
+				default:
+					throw new DataAccessException(
+						string.Format("Unknown action '{0}'.", actionName));
+			}
+		}
+
+		private static readonly Hashtable _actionSqlQueryInfo = new Hashtable();
+
+		[NoInterception]
+		public virtual SqlQueryInfo GetSqlQueryInfo(DbManager db, Type type, string actionName)
+		{
+			var key   = type.FullName + "$" + actionName + "$" + db.DataProvider.UniqueName + "$" + GetTableName(type);
+			var query = (SqlQueryInfo)_actionSqlQueryInfo[key];
+
+			if (query == null)
+			{
+				query = CreateSqlText(db, type, actionName);
+				_actionSqlQueryInfo[key] = query;
+			}
+
+			return query;
+		}
+
+		#endregion
+	}
+}