0
|
1 #region
|
|
2
|
|
3 using System;
|
|
4 using System.Collections;
|
|
5 using System.Collections.Generic;
|
|
6 using System.Data;
|
|
7 using System.Linq;
|
|
8 using BLToolkit.Data;
|
|
9 using BLToolkit.Reflection.Extension;
|
|
10
|
|
11 #endregion
|
|
12
|
|
13 namespace BLToolkit.Mapping
|
|
14 {
|
|
15 public class FullMappingSchema : MappingSchema
|
|
16 {
|
|
17 #region Fields
|
|
18
|
|
19 private readonly DbManager _db;
|
|
20 private readonly bool _ignoreLazyLoad;
|
|
21 private DataTable _schema;
|
|
22 private List<string> _schemaColumns;
|
|
23 private readonly MappingSchema _parentMappingSchema;
|
|
24 private readonly FactoryType _factoryType;
|
|
25
|
|
26 private ExtensionList _extensions;
|
|
27
|
|
28 #endregion
|
|
29
|
|
30 public FullMappingSchema(DbManager db, bool ignoreLazyLoad = false, MappingSchema parentMappingSchema = null,
|
|
31 FactoryType factoryType = FactoryType.LazyLoading)
|
|
32 {
|
|
33 _db = db;
|
|
34 _parentMappingSchema = parentMappingSchema;
|
|
35 _factoryType = factoryType;
|
|
36 _ignoreLazyLoad = ignoreLazyLoad;
|
|
37 }
|
|
38
|
|
39 #region Overrides
|
|
40
|
|
41 public override ExtensionList Extensions
|
|
42 {
|
|
43 get
|
|
44 {
|
|
45 if (_parentMappingSchema != null)
|
|
46 return this._parentMappingSchema.Extensions;
|
|
47 return _extensions;
|
|
48 }
|
|
49 set
|
|
50 {
|
|
51 if (_parentMappingSchema != null)
|
|
52 this._parentMappingSchema.Extensions = value;
|
|
53 _extensions = value;
|
|
54 }
|
|
55 }
|
|
56
|
|
57 protected override ObjectMapper CreateObjectMapperInstance(Type type)
|
|
58 {
|
|
59 return new FullObjectMapper(_db, _ignoreLazyLoad,_factoryType);
|
|
60 }
|
|
61
|
|
62 protected override void MapInternal(Reflection.InitContext initContext, IMapDataSource source, object sourceObject, IMapDataDestination dest, object destObject, params object[] parameters)
|
|
63 {
|
|
64 FullObjectMapper mapper = (FullObjectMapper)initContext.ObjectMapper;
|
|
65 IDataReader dataReader = (IDataReader)sourceObject;
|
|
66
|
|
67 //int[] index = GetIndex(source, dest);
|
|
68 //IValueMapper[] mappers = GetValueMappers(source, dest, index);
|
|
69
|
|
70 //foreach (var valueMapper in mappers)
|
|
71 //{
|
|
72
|
|
73 //}
|
|
74
|
|
75 InitSchema(dataReader);
|
|
76
|
|
77 if (mapper.ColParent)
|
|
78 {
|
|
79 FillObject(mapper, dataReader, destObject);
|
|
80 while (dataReader.Read())
|
|
81 {
|
|
82 destObject = FillObject(destObject, mapper, dataReader);
|
|
83 }
|
|
84 }
|
|
85 else
|
|
86 FillObject(mapper, dataReader, destObject);
|
|
87 }
|
|
88
|
|
89 public override IList MapDataReaderToList(
|
|
90 IDataReader reader,
|
|
91 IList list,
|
|
92 Type destObjectType,
|
|
93 params object[] parameters)
|
|
94 {
|
|
95 return internalMapDataReaderToList(reader, list, destObjectType, parameters);
|
|
96 }
|
|
97
|
|
98 #endregion
|
|
99
|
|
100 #region Private methods
|
|
101
|
|
102 private object FillObject(object result, IObjectMapper mapper, IDataReader datareader)
|
|
103 {
|
|
104 foreach (IMapper map in mapper.PropertiesMapping)
|
|
105 {
|
|
106 if (map is IObjectMapper && (map as IObjectMapper).IsLazy)
|
|
107 continue;
|
|
108
|
|
109 if (map is CollectionFullObjectMapper)
|
|
110 {
|
|
111 var collectionFullObjectMapper = (CollectionFullObjectMapper) map;
|
|
112 object listInstance = collectionFullObjectMapper.Getter(result);
|
|
113 if (listInstance == null)
|
|
114 {
|
|
115 listInstance = Activator.CreateInstance((map as CollectionFullObjectMapper).PropertyCollectionType);
|
|
116 map.Setter(result, listInstance);
|
|
117 }
|
|
118 var list = (IList) listInstance;
|
|
119 object fillObject = ((CollectionFullObjectMapper)map).CreateInstance();
|
|
120 FillObject((CollectionFullObjectMapper) map, datareader, fillObject);
|
|
121
|
|
122 if (list.Count > 0)
|
|
123 {
|
|
124 var curMapper = (FullObjectMapper)GetObjectMapper(fillObject.GetType());
|
|
125
|
|
126 object lastElement = list[list.Count - 1];
|
|
127
|
|
128 bool allPksEqual = true;
|
|
129
|
|
130 //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!
|
|
131 /*foreach (var pkIndex in pkIndexes)
|
|
132 {
|
|
133 var dbValue = reader.GetValue(pkIndex);
|
|
134 if (dbValue == DBNull.Value)
|
|
135 {
|
|
136 pkIsNull = true;
|
|
137 break;
|
|
138 }
|
|
139 }*/
|
|
140
|
|
141 foreach (var pkGetter in curMapper.PrimaryKeyValueGetters)
|
|
142 {
|
|
143 object lastPk = pkGetter.Invoke(lastElement);
|
|
144 object currentPk = pkGetter.Invoke(fillObject);
|
|
145
|
|
146 if (!lastPk.Equals(currentPk))
|
|
147 {
|
|
148 allPksEqual = false;
|
|
149 break;
|
|
150 }
|
|
151 }
|
|
152
|
|
153 if (allPksEqual)
|
|
154 continue;
|
|
155 }
|
|
156
|
|
157 ((IList) listInstance).Add(fillObject);
|
|
158 }
|
|
159 }
|
|
160
|
|
161 return result;
|
|
162 }
|
|
163
|
|
164 private void FillObject(IObjectMapper mapper, IDataReader datareader, object result)
|
|
165 {
|
|
166 foreach (IMapper map in mapper.PropertiesMapping)
|
|
167 {
|
|
168 if (map is IObjectMapper && (map as IObjectMapper).IsLazy)
|
|
169 continue;
|
|
170
|
|
171 if (map is ValueMapper)
|
|
172 {
|
|
173 if (((ValueMapper)map).SetDataReaderIndex(_schemaColumns))
|
|
174 continue;
|
|
175 }
|
|
176
|
|
177 if (datareader.IsDBNull(map.DataReaderIndex))
|
|
178 continue;
|
|
179
|
|
180 if (map is ValueMapper)
|
|
181 {
|
|
182 object value = datareader.GetValue(map.DataReaderIndex);
|
|
183
|
|
184 try
|
|
185 {
|
|
186 map.Setter(result, value);
|
|
187 }
|
|
188 catch (Exception exception)
|
|
189 {
|
|
190 throw new Exception(
|
|
191 string.Format("FillOject failed for field : {0} of class: {1}.\nColumn name : {2} Db type is: {3} and value : {4}",
|
|
192 map.PropertyName, mapper.PropertyType,
|
|
193 ((ValueMapper) map).ColumnName,
|
|
194 value == null ? "Null" : value.GetType().ToString(), value), exception);
|
|
195 }
|
|
196 }
|
|
197
|
|
198 if (map is FullObjectMapper)
|
|
199 {
|
|
200 object fillObject = ((FullObjectMapper) map).CreateInstance();
|
|
201 FillObject((FullObjectMapper) map, datareader, fillObject);
|
|
202 map.Setter(result, fillObject);
|
|
203 }
|
|
204
|
|
205 if (map is CollectionFullObjectMapper)
|
|
206 {
|
|
207 var collectionFullObjectMapper = (CollectionFullObjectMapper) map;
|
|
208
|
|
209 object listInstance = collectionFullObjectMapper.Getter(result);
|
|
210 if (listInstance == null)
|
|
211 {
|
|
212 listInstance = Activator.CreateInstance((map as CollectionFullObjectMapper).PropertyCollectionType);
|
|
213 map.Setter(result, listInstance);
|
|
214 }
|
|
215
|
|
216 object fillObject = ((CollectionFullObjectMapper)map).CreateInstance();
|
|
217 FillObject((CollectionFullObjectMapper) map, datareader, fillObject);
|
|
218 ((IList) listInstance).Add(fillObject);
|
|
219 }
|
|
220 }
|
|
221 }
|
|
222
|
|
223 private void InitSchema(IDataReader reader)
|
|
224 {
|
|
225 _schemaColumns = new List<string>();
|
|
226 _schema = reader.GetSchemaTable();
|
|
227 if (_schema != null)
|
|
228 _schema.Rows.Cast<DataRow>().ToList().ForEach(dr => _schemaColumns.Add((string)dr["ColumnName"]));
|
|
229 }
|
|
230
|
|
231 private IList internalMapDataReaderToList(
|
|
232 IDataReader reader,
|
|
233 IList list,
|
|
234 Type destObjectType,
|
|
235 params object[] parameters)
|
|
236 {
|
|
237 FullObjectMapper mapper = (FullObjectMapper)GetObjectMapper(destObjectType);
|
|
238
|
|
239 InitSchema(reader);
|
|
240
|
|
241 object currentItem = null;
|
|
242
|
|
243 List<int> pkIndexes = new List<int>();
|
|
244 foreach (var nm in mapper.PrimaryKeyNames)
|
|
245 {
|
|
246 pkIndexes.Add(mapper.PropertiesMapping.First(x => x.PropertyName == nm).DataReaderIndex);
|
|
247 }
|
|
248
|
|
249 while (reader.Read())
|
|
250 {
|
|
251 var result = mapper.CreateInstance();
|
|
252
|
|
253 FillObject(mapper, reader, result);
|
|
254 if (currentItem == null)
|
|
255 {
|
|
256 currentItem = result;
|
|
257 list.Add(result);
|
|
258 continue;
|
|
259 }
|
|
260
|
|
261 bool pkIsNull = false;
|
|
262 bool allPksEqual = true;
|
|
263
|
|
264 //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!
|
|
265 foreach (var pkIndex in pkIndexes)
|
|
266 {
|
|
267 var dbValue = reader.GetValue(pkIndex);
|
|
268 if (dbValue == DBNull.Value)
|
|
269 {
|
|
270 pkIsNull = true;
|
|
271 break;
|
|
272 }
|
|
273 }
|
|
274
|
|
275 if (!pkIsNull)
|
|
276 foreach (var pkGetter in mapper.PrimaryKeyValueGetters)
|
|
277 {
|
|
278 object resultPk = pkGetter.Invoke(result);
|
|
279 object currentItemPk = pkGetter.Invoke(currentItem);
|
|
280
|
|
281 if (!resultPk.Equals(currentItemPk))
|
|
282 {
|
|
283 allPksEqual = false;
|
|
284 break;
|
|
285 }
|
|
286 }
|
|
287
|
|
288 if (!pkIsNull && !allPksEqual)
|
|
289 {
|
|
290 currentItem = result;
|
|
291 list.Add(result);
|
|
292 //continue;
|
|
293 }
|
|
294
|
|
295 if (mapper.ColParent)
|
|
296 {
|
|
297 FillObject(currentItem, mapper, reader);
|
|
298 }
|
|
299 }
|
|
300
|
|
301 return list;
|
|
302 }
|
|
303
|
|
304 #endregion
|
|
305 }
|
|
306 } |