Mercurial > pub > bltoolkit
diff Extensions/JointureAddOn/Mapping/FullMappingSchema.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/Extensions/JointureAddOn/Mapping/FullMappingSchema.cs Thu Mar 27 21:46:09 2014 +0400 @@ -0,0 +1,306 @@ +#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 + } +} \ No newline at end of file