Mercurial > pub > bltoolkit
view Extensions/JointureAddOn/Mapping/FullMappingSchema.cs @ 4:f757da6161a1
!bug 100 + 2h fixed gregression
author | cin |
---|---|
date | Sun, 24 Aug 2014 17:57:42 +0400 |
parents | f990fcb411a9 |
children |
line wrap: on
line source
#region using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Linq; using BLToolkit.Data; using BLToolkit.Reflection.Extension; #endregion namespace BLToolkit.Mapping { public class FullMappingSchema : MappingSchema { #region Fields private readonly DbManager _db; private readonly bool _ignoreLazyLoad; private DataTable _schema; private List<string> _schemaColumns; private readonly MappingSchema _parentMappingSchema; private readonly FactoryType _factoryType; private ExtensionList _extensions; #endregion public FullMappingSchema(DbManager db, bool ignoreLazyLoad = false, MappingSchema parentMappingSchema = null, FactoryType factoryType = FactoryType.LazyLoading) { _db = db; _parentMappingSchema = parentMappingSchema; _factoryType = factoryType; _ignoreLazyLoad = ignoreLazyLoad; } #region Overrides public override ExtensionList Extensions { get { if (_parentMappingSchema != null) return this._parentMappingSchema.Extensions; return _extensions; } set { if (_parentMappingSchema != null) this._parentMappingSchema.Extensions = value; _extensions = value; } } protected override ObjectMapper CreateObjectMapperInstance(Type type) { return new FullObjectMapper(_db, _ignoreLazyLoad,_factoryType); } protected override void MapInternal(Reflection.InitContext initContext, IMapDataSource source, object sourceObject, IMapDataDestination dest, object destObject, params object[] parameters) { FullObjectMapper mapper = (FullObjectMapper)initContext.ObjectMapper; IDataReader dataReader = (IDataReader)sourceObject; //int[] index = GetIndex(source, dest); //IValueMapper[] mappers = GetValueMappers(source, dest, index); //foreach (var valueMapper in mappers) //{ //} InitSchema(dataReader); if (mapper.ColParent) { FillObject(mapper, dataReader, destObject); while (dataReader.Read()) { destObject = FillObject(destObject, mapper, dataReader); } } else FillObject(mapper, dataReader, destObject); } public override IList MapDataReaderToList( IDataReader reader, IList list, Type destObjectType, params object[] parameters) { return internalMapDataReaderToList(reader, list, destObjectType, parameters); } #endregion #region Private methods private object FillObject(object result, IObjectMapper mapper, IDataReader datareader) { foreach (IMapper map in mapper.PropertiesMapping) { if (map is IObjectMapper && (map as IObjectMapper).IsLazy) continue; if (map is CollectionFullObjectMapper) { var collectionFullObjectMapper = (CollectionFullObjectMapper) map; object listInstance = collectionFullObjectMapper.Getter(result); if (listInstance == null) { listInstance = Activator.CreateInstance((map as CollectionFullObjectMapper).PropertyCollectionType); map.Setter(result, listInstance); } var list = (IList) listInstance; object fillObject = ((CollectionFullObjectMapper)map).CreateInstance(); FillObject((CollectionFullObjectMapper) map, datareader, fillObject); if (list.Count > 0) { var curMapper = (FullObjectMapper)GetObjectMapper(fillObject.GetType()); object lastElement = list[list.Count - 1]; bool allPksEqual = true; //This is needed, because DBValue can be Null, but the Field can be Guid, wich then is filled with Guid.Empty and this is also a valid value! /*foreach (var pkIndex in pkIndexes) { var dbValue = reader.GetValue(pkIndex); if (dbValue == DBNull.Value) { pkIsNull = true; break; } }*/ foreach (var pkGetter in curMapper.PrimaryKeyValueGetters) { object lastPk = pkGetter.Invoke(lastElement); object currentPk = pkGetter.Invoke(fillObject); if (!lastPk.Equals(currentPk)) { allPksEqual = false; break; } } if (allPksEqual) continue; } ((IList) listInstance).Add(fillObject); } } return result; } private void FillObject(IObjectMapper mapper, IDataReader datareader, object result) { foreach (IMapper map in mapper.PropertiesMapping) { if (map is IObjectMapper && (map as IObjectMapper).IsLazy) continue; if (map is ValueMapper) { if (((ValueMapper)map).SetDataReaderIndex(_schemaColumns)) continue; } if (datareader.IsDBNull(map.DataReaderIndex)) continue; if (map is ValueMapper) { object value = datareader.GetValue(map.DataReaderIndex); try { map.Setter(result, value); } catch (Exception exception) { throw new Exception( string.Format("FillOject failed for field : {0} of class: {1}.\nColumn name : {2} Db type is: {3} and value : {4}", map.PropertyName, mapper.PropertyType, ((ValueMapper) map).ColumnName, value == null ? "Null" : value.GetType().ToString(), value), exception); } } if (map is FullObjectMapper) { object fillObject = ((FullObjectMapper) map).CreateInstance(); FillObject((FullObjectMapper) map, datareader, fillObject); map.Setter(result, fillObject); } if (map is CollectionFullObjectMapper) { var collectionFullObjectMapper = (CollectionFullObjectMapper) map; object listInstance = collectionFullObjectMapper.Getter(result); if (listInstance == null) { listInstance = Activator.CreateInstance((map as CollectionFullObjectMapper).PropertyCollectionType); map.Setter(result, listInstance); } object fillObject = ((CollectionFullObjectMapper)map).CreateInstance(); FillObject((CollectionFullObjectMapper) map, datareader, fillObject); ((IList) listInstance).Add(fillObject); } } } private void InitSchema(IDataReader reader) { _schemaColumns = new List<string>(); _schema = reader.GetSchemaTable(); if (_schema != null) _schema.Rows.Cast<DataRow>().ToList().ForEach(dr => _schemaColumns.Add((string)dr["ColumnName"])); } private IList internalMapDataReaderToList( IDataReader reader, IList list, Type destObjectType, params object[] parameters) { FullObjectMapper mapper = (FullObjectMapper)GetObjectMapper(destObjectType); InitSchema(reader); object currentItem = null; List<int> pkIndexes = new List<int>(); foreach (var nm in mapper.PrimaryKeyNames) { pkIndexes.Add(mapper.PropertiesMapping.First(x => x.PropertyName == nm).DataReaderIndex); } while (reader.Read()) { var result = mapper.CreateInstance(); FillObject(mapper, reader, result); if (currentItem == null) { currentItem = result; list.Add(result); continue; } bool pkIsNull = false; bool allPksEqual = true; //This is needed, because DBValue can be Null, but the Field can be Guid, wich then is filled with Guid.Empty and this is also a valid value! foreach (var pkIndex in pkIndexes) { var dbValue = reader.GetValue(pkIndex); if (dbValue == DBNull.Value) { pkIsNull = true; break; } } if (!pkIsNull) foreach (var pkGetter in mapper.PrimaryKeyValueGetters) { object resultPk = pkGetter.Invoke(result); object currentItemPk = pkGetter.Invoke(currentItem); if (!resultPk.Equals(currentItemPk)) { allPksEqual = false; break; } } if (!pkIsNull && !allPksEqual) { currentItem = result; list.Add(result); //continue; } if (mapper.ColParent) { FillObject(currentItem, mapper, reader); } } return list; } #endregion } }