Mercurial > pub > bltoolkit
comparison Source/DataAccess/SqlQueryBase.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; | |
| 3 using System.Collections.Generic; | |
| 4 using System.Text; | |
| 5 | |
| 6 using BLToolkit.Aspects; | |
| 7 using BLToolkit.Data; | |
| 8 using BLToolkit.Data.DataProvider; | |
| 9 using BLToolkit.Mapping; | |
| 10 using BLToolkit.Reflection; | |
| 11 using BLToolkit.Reflection.Extension; | |
| 12 | |
| 13 namespace BLToolkit.DataAccess | |
| 14 { | |
| 15 public abstract class SqlQueryBase : DataAccessorBase | |
| 16 { | |
| 17 #region Constructors | |
| 18 | |
| 19 protected SqlQueryBase() | |
| 20 { | |
| 21 } | |
| 22 | |
| 23 protected SqlQueryBase(DbManager dbManager) | |
| 24 : base(dbManager) | |
| 25 { | |
| 26 } | |
| 27 | |
| 28 protected SqlQueryBase(DbManager dbManager, bool dispose) | |
| 29 : base(dbManager, dispose) | |
| 30 { | |
| 31 } | |
| 32 | |
| 33 #endregion | |
| 34 | |
| 35 #region Protected Members | |
| 36 | |
| 37 [NoInterception] | |
| 38 protected virtual MemberMapper[] GetFieldList(ObjectMapper om) | |
| 39 { | |
| 40 var list = new List<MemberMapper>(om.Count); | |
| 41 | |
| 42 foreach (MemberMapper mm in om) | |
| 43 if (mm.MapMemberInfo.SqlIgnore == false) | |
| 44 list.Add(mm); | |
| 45 | |
| 46 return list.ToArray(); | |
| 47 } | |
| 48 | |
| 49 [NoInterception] | |
| 50 protected virtual MemberMapper[] GetNonKeyFieldList(ObjectMapper om) | |
| 51 { | |
| 52 var typeExt = TypeExtension.GetTypeExtension(om.TypeAccessor.OriginalType, Extensions); | |
| 53 var list = new List<MemberMapper>(); | |
| 54 | |
| 55 foreach (MemberMapper mm in om) | |
| 56 { | |
| 57 if (mm.MapMemberInfo.SqlIgnore) | |
| 58 continue; | |
| 59 | |
| 60 var ma = mm.MapMemberInfo.MemberAccessor; | |
| 61 | |
| 62 bool isSet; | |
| 63 MappingSchema.MetadataProvider.GetPrimaryKeyOrder(om.TypeAccessor.OriginalType, typeExt, ma, out isSet); | |
| 64 | |
| 65 if (!isSet) | |
| 66 list.Add(mm); | |
| 67 } | |
| 68 | |
| 69 return list.ToArray(); | |
| 70 } | |
| 71 | |
| 72 struct MemberOrder | |
| 73 { | |
| 74 public MemberOrder(MemberMapper memberMapper, int order) | |
| 75 { | |
| 76 MemberMapper = memberMapper; | |
| 77 Order = order; | |
| 78 } | |
| 79 | |
| 80 public readonly MemberMapper MemberMapper; | |
| 81 public readonly int Order; | |
| 82 } | |
| 83 | |
| 84 private static readonly Hashtable _keyList = new Hashtable(); | |
| 85 | |
| 86 [NoInterception] | |
| 87 protected internal virtual MemberMapper[] GetKeyFieldList(DbManager db, Type type) | |
| 88 { | |
| 89 var key = type.FullName + "$" + db.DataProvider.UniqueName; | |
| 90 var mmList = (MemberMapper[])_keyList[key]; | |
| 91 | |
| 92 if (mmList == null) | |
| 93 { | |
| 94 var typeExt = TypeExtension.GetTypeExtension(type, Extensions); | |
| 95 var list = new List<MemberOrder>(); | |
| 96 | |
| 97 foreach (MemberMapper mm in db.MappingSchema.GetObjectMapper(type)) | |
| 98 { | |
| 99 if (mm.MapMemberInfo.SqlIgnore) | |
| 100 continue; | |
| 101 | |
| 102 var ma = mm.MapMemberInfo.MemberAccessor; | |
| 103 | |
| 104 if (TypeHelper.IsScalar(ma.Type)) | |
| 105 { | |
| 106 bool isSet; | |
| 107 var order = MappingSchema.MetadataProvider.GetPrimaryKeyOrder(type, typeExt, ma, out isSet); | |
| 108 | |
| 109 if (isSet) | |
| 110 list.Add(new MemberOrder(mm, order)); | |
| 111 } | |
| 112 } | |
| 113 | |
| 114 list.Sort((x, y) => x.Order - y.Order); | |
| 115 | |
| 116 _keyList[key] = mmList = new MemberMapper[list.Count]; | |
| 117 | |
| 118 for (var i = 0; i < list.Count; i++) | |
| 119 mmList[i] = list[i].MemberMapper; | |
| 120 } | |
| 121 | |
| 122 return mmList; | |
| 123 } | |
| 124 | |
| 125 [NoInterception] | |
| 126 protected virtual void AddWherePK(DbManager db, SqlQueryInfo query, StringBuilder sb, int nParameter) | |
| 127 { | |
| 128 sb.Append("WHERE\n"); | |
| 129 | |
| 130 var memberMappers = GetKeyFieldList(db, query.ObjectType); | |
| 131 | |
| 132 if (memberMappers.Length == 0) | |
| 133 throw new DataAccessException( | |
| 134 string.Format("No primary key field(s) in the type '{0}'.", query.ObjectType.FullName)); | |
| 135 | |
| 136 foreach (var mm in memberMappers) | |
| 137 { | |
| 138 var p = query.AddParameter( | |
| 139 db.DataProvider.Convert(mm.Name + "_W", ConvertType.NameToQueryParameter).ToString(), | |
| 140 mm.Name); | |
| 141 | |
| 142 sb.AppendFormat("\t{0} = ", db.DataProvider.Convert(p.FieldName, ConvertType.NameToQueryField)); | |
| 143 | |
| 144 if (nParameter < 0) | |
| 145 sb.AppendFormat("{0} AND\n", p.ParameterName); | |
| 146 else | |
| 147 sb.AppendFormat("{{{0}}} AND\n", nParameter++); | |
| 148 } | |
| 149 | |
| 150 sb.Remove(sb.Length - 5, 5); | |
| 151 } | |
| 152 | |
| 153 protected SqlQueryInfo CreateSelectByKeySqlText(DbManager db, Type type) | |
| 154 { | |
| 155 var om = db.MappingSchema.GetObjectMapper(type); | |
| 156 var sb = new StringBuilder(); | |
| 157 var query = new SqlQueryInfo(om); | |
| 158 | |
| 159 sb.Append("SELECT\n"); | |
| 160 | |
| 161 foreach (var mm in GetFieldList(om)) | |
| 162 sb.AppendFormat("\t{0},\n", | |
| 163 db.DataProvider.Convert(mm.Name, ConvertType.NameToQueryField)); | |
| 164 | |
| 165 sb.Remove(sb.Length - 2, 1); | |
| 166 | |
| 167 sb.Append("FROM\n\t"); | |
| 168 | |
| 169 AppendTableName(sb, db, type); | |
| 170 | |
| 171 AddWherePK(db, query, sb, -1); | |
| 172 | |
| 173 query.QueryText = sb.ToString(); | |
| 174 | |
| 175 return query; | |
| 176 } | |
| 177 | |
| 178 // NOTE changed to virtual | |
| 179 protected virtual void AppendTableName(StringBuilder sb, DbManager db, Type type) | |
| 180 { | |
| 181 var database = GetDatabaseName(type); | |
| 182 var owner = GetOwnerName (type); | |
| 183 var name = GetTableName (type); | |
| 184 | |
| 185 db.DataProvider.CreateSqlProvider().BuildTableName(sb, | |
| 186 database == null ? null : db.DataProvider.Convert(database, ConvertType.NameToDatabase). ToString(), | |
| 187 owner == null ? null : db.DataProvider.Convert(owner, ConvertType.NameToOwner). ToString(), | |
| 188 name == null ? null : db.DataProvider.Convert(name, ConvertType.NameToQueryTable).ToString()); | |
| 189 | |
| 190 sb.AppendLine(); | |
| 191 } | |
| 192 | |
| 193 protected SqlQueryInfo CreateSelectAllSqlText(DbManager db, Type type) | |
| 194 { | |
| 195 var om = db.MappingSchema.GetObjectMapper(type); | |
| 196 var sb = new StringBuilder(); | |
| 197 var query = new SqlQueryInfo(om); | |
| 198 | |
| 199 sb.Append("SELECT\n"); | |
| 200 | |
| 201 foreach (var mm in GetFieldList(om)) | |
| 202 sb.AppendFormat("\t{0},\n", | |
| 203 db.DataProvider.Convert(mm.Name, ConvertType.NameToQueryField)); | |
| 204 | |
| 205 sb.Remove(sb.Length - 2, 1); | |
| 206 | |
| 207 sb.Append("FROM\n\t"); | |
| 208 AppendTableName(sb, db, type); | |
| 209 | |
| 210 query.QueryText = sb.ToString(); | |
| 211 | |
| 212 return query; | |
| 213 } | |
| 214 | |
| 215 protected SqlQueryInfo CreateInsertSqlText(DbManager db, Type type, int nParameter) | |
| 216 { | |
| 217 var typeExt = TypeExtension.GetTypeExtension(type, Extensions); | |
| 218 var om = db.MappingSchema.GetObjectMapper(type); | |
| 219 var list = new List<MemberMapper>(); | |
| 220 var sb = new StringBuilder(); | |
| 221 var query = new SqlQueryInfo(om); | |
| 222 var mp = MappingSchema.MetadataProvider; | |
| 223 | |
| 224 sb.Append("INSERT INTO "); | |
| 225 AppendTableName(sb, db, type); | |
| 226 sb.Append(" (\n"); | |
| 227 | |
| 228 foreach (var mm in GetFieldList(om)) | |
| 229 { | |
| 230 // IT: This works incorrectly for complex mappers. | |
| 231 // | |
| 232 // [2009-03-24] ili: use mm.MemberAccessor instead of mm.ComplexMemberAccessor | |
| 233 // as in CreateUpdateSqlText | |
| 234 // | |
| 235 | |
| 236 bool isSet; | |
| 237 var nonUpdatableAttribute = mp.GetNonUpdatableAttribute(type, typeExt, mm.MapMemberInfo.MemberAccessor, out isSet); | |
| 238 | |
| 239 if (nonUpdatableAttribute == null || !isSet || nonUpdatableAttribute.OnInsert == false) | |
| 240 { | |
| 241 sb.AppendFormat("\t{0},\n", | |
| 242 db.DataProvider.Convert(mm.Name, ConvertType.NameToQueryField)); | |
| 243 list.Add(mm); | |
| 244 } | |
| 245 } | |
| 246 | |
| 247 sb.Remove(sb.Length - 2, 1); | |
| 248 | |
| 249 sb.Append(") VALUES (\n"); | |
| 250 | |
| 251 foreach (var mm in list) | |
| 252 { | |
| 253 var p = query.AddParameter( | |
| 254 db.DataProvider.Convert(mm.Name + "_P", ConvertType.NameToQueryParameter).ToString(), | |
| 255 mm.Name); | |
| 256 | |
| 257 if (nParameter < 0) | |
| 258 sb.AppendFormat("\t{0},\n", p.ParameterName); | |
| 259 //sb.AppendFormat("\t{0},\n", db.DataProvider.Convert(p.ParameterName, ConvertType.NameToQueryParameter)); | |
| 260 else | |
| 261 sb.AppendFormat("\t{{{0}}},\n", nParameter++); | |
| 262 } | |
| 263 | |
| 264 sb.Remove(sb.Length - 2, 1); | |
| 265 | |
| 266 sb.Append(")"); | |
| 267 | |
| 268 query.QueryText = sb.ToString(); | |
| 269 | |
| 270 return query; | |
| 271 } | |
| 272 | |
| 273 protected SqlQueryInfo CreateUpdateSqlText(DbManager db, Type type, int nParameter) | |
| 274 { | |
| 275 var typeExt = TypeExtension.GetTypeExtension(type, Extensions); | |
| 276 var om = db.MappingSchema.GetObjectMapper(type); | |
| 277 var sb = new StringBuilder(); | |
| 278 var query = new SqlQueryInfo(om); | |
| 279 var mp = MappingSchema.MetadataProvider; | |
| 280 | |
| 281 sb.Append("UPDATE\n\t"); | |
| 282 AppendTableName(sb, db, type); | |
| 283 sb.Append("\nSET\n"); | |
| 284 | |
| 285 var fields = GetFieldList(om); | |
| 286 var hasFields = false; | |
| 287 | |
| 288 foreach (var mm in fields) | |
| 289 { | |
| 290 bool isSet; | |
| 291 | |
| 292 var nonUpdatableAttribute = mp.GetNonUpdatableAttribute(type, typeExt, mm.MapMemberInfo.MemberAccessor, out isSet); | |
| 293 | |
| 294 if (nonUpdatableAttribute != null && isSet && nonUpdatableAttribute.OnUpdate == true) | |
| 295 continue; | |
| 296 | |
| 297 mp.GetPrimaryKeyOrder(type, typeExt, mm.MapMemberInfo.MemberAccessor, out isSet); | |
| 298 | |
| 299 if (isSet) | |
| 300 continue; | |
| 301 | |
| 302 hasFields = true; | |
| 303 | |
| 304 var p = query.AddParameter( | |
| 305 db.DataProvider.Convert(mm.Name + "_P", ConvertType.NameToQueryParameter).ToString(), | |
| 306 mm.Name); | |
| 307 | |
| 308 sb.AppendFormat("\t{0} = ", db.DataProvider.Convert(p.FieldName, ConvertType.NameToQueryField)); | |
| 309 | |
| 310 if (nParameter < 0) | |
| 311 sb.AppendFormat("{0},\n", p.ParameterName); | |
| 312 else | |
| 313 sb.AppendFormat("\t{{{0}}},\n", nParameter++); | |
| 314 } | |
| 315 | |
| 316 if (!hasFields) | |
| 317 throw new DataAccessException( | |
| 318 string.Format("There are no fields to update in the type '{0}'.", query.ObjectType.FullName)); | |
| 319 | |
| 320 sb.Remove(sb.Length - 2, 1); | |
| 321 | |
| 322 AddWherePK(db, query, sb, nParameter); | |
| 323 | |
| 324 query.QueryText = sb.ToString(); | |
| 325 | |
| 326 return query; | |
| 327 } | |
| 328 | |
| 329 protected SqlQueryInfo CreateDeleteSqlText(DbManager db, Type type, int nParameter) | |
| 330 { | |
| 331 var om = db.MappingSchema.GetObjectMapper(type); | |
| 332 var sb = new StringBuilder(); | |
| 333 var query = new SqlQueryInfo(om); | |
| 334 | |
| 335 sb.Append("DELETE FROM\n\t"); | |
| 336 AppendTableName(sb, db, type); | |
| 337 sb.AppendLine(); | |
| 338 | |
| 339 AddWherePK(db, query, sb, nParameter); | |
| 340 | |
| 341 query.QueryText = sb.ToString(); | |
| 342 | |
| 343 return query; | |
| 344 } | |
| 345 | |
| 346 [NoInterception] | |
| 347 protected virtual SqlQueryInfo CreateSqlText(DbManager db, Type type, string actionName) | |
| 348 { | |
| 349 switch (actionName) | |
| 350 { | |
| 351 case "SelectByKey": return CreateSelectByKeySqlText(db, type); | |
| 352 case "SelectAll": return CreateSelectAllSqlText (db, type); | |
| 353 case "Insert": return CreateInsertSqlText (db, type, -1); | |
| 354 case "InsertBatch": return CreateInsertSqlText (db, type, 0); | |
| 355 case "Update": return CreateUpdateSqlText (db, type, -1); | |
| 356 case "UpdateBatch": return CreateUpdateSqlText (db, type, 0); | |
| 357 case "Delete": return CreateDeleteSqlText (db, type, -1); | |
| 358 case "DeleteBatch": return CreateDeleteSqlText (db, type, 0); | |
| 359 default: | |
| 360 throw new DataAccessException( | |
| 361 string.Format("Unknown action '{0}'.", actionName)); | |
| 362 } | |
| 363 } | |
| 364 | |
| 365 private static readonly Hashtable _actionSqlQueryInfo = new Hashtable(); | |
| 366 | |
| 367 [NoInterception] | |
| 368 public virtual SqlQueryInfo GetSqlQueryInfo(DbManager db, Type type, string actionName) | |
| 369 { | |
| 370 var key = type.FullName + "$" + actionName + "$" + db.DataProvider.UniqueName + "$" + GetTableName(type); | |
| 371 var query = (SqlQueryInfo)_actionSqlQueryInfo[key]; | |
| 372 | |
| 373 if (query == null) | |
| 374 { | |
| 375 query = CreateSqlText(db, type, actionName); | |
| 376 _actionSqlQueryInfo[key] = query; | |
| 377 } | |
| 378 | |
| 379 return query; | |
| 380 } | |
| 381 | |
| 382 #endregion | |
| 383 } | |
| 384 } |
