protected IDataModelCollection LoadModels(Type modelType, IDataModelQuery query, DbTransaction transactionContext) { MethodInfo mi = GetType().GetMadeGenericMethod(MethodBase.GetCurrentMethod().Name, new[] { modelType }, new[] { typeof(DataModelQuery <>), typeof(DbTransaction) }); return((IDataModelCollection)mi.Invoke(this, new object[] { query, transactionContext })); }
protected IDataModelCollection DeepLoadModels(Type modelType, IDataModelQuery query, int?depth, DbTransaction transactionContext, List <DataModel> loadedModels) { MethodInfo mi = GetType().GetMadeGenericMethod(MethodBase.GetCurrentMethod().Name, new[] { modelType }, new[] { typeof(DataModelQuery <>), typeof(int?), typeof(DbTransaction), typeof(List <DataModel>) }); return((IDataModelCollection)mi.Invoke(this, new object[] { query, depth, transactionContext, loadedModels })); }
private void LoadMember( DataModel dataModel, int?depth, DataModelColumnAttribute fieldMapping, string memberName, DbTransaction transactionContext, List <DataModel> loadedModels) { DataModelColumnAttribute field = fieldMapping; DataModel e = dataModel; ForeignKeyAttribute fkmapping = field.ForeignKeyMapping; string fMemberName = field.ForeignKeyMapping.AssignToMember; FieldInfo memField = e.Entity.GetType().GetField(fMemberName); PropertyInfo memProp = e.Entity.GetType().GetProperty(fMemberName); Type memberType = memField != null ? memField.FieldType : memProp.PropertyType; bool useAssignWrapper = false; if (!memberType.IsDataModel()) { useAssignWrapper = true; } Type dataMemberType; dataMemberType = useAssignWrapper ? typeof(DataModel <>).MakeGenericType(memberType) : memberType; Type queryType = typeof(DataModelQuery <>).MakeGenericType(dataMemberType); IDataModelQuery subquery = ((IDataModelQuery)Activator.CreateInstance(queryType)) .WhereProperty[fkmapping.ForeignEntityProperty].IsEqualTo(e[memberName]); if (depth != null) { depth = depth - 1; } DataModel subentity = DeepLoadModel(dataMemberType, subquery, depth, transactionContext, loadedModels); if (useAssignWrapper) { memProp.SetValue( e.Entity, subentity.Entity, new object[] {}); } else { memProp.SetValue(e, subentity, new object[] {}); } }
/// <summary> /// When implemented, loads the full object graph for the first /// <see cref="DataModel"/> that is returned from the specified /// <paramref name="query"/>, within the specified database /// <paramref name="transactionContext"/>. /// </summary> /// <param name="query"></param> /// <param name="transactionContext"></param> /// <param name="depth"></param> /// <param name="loadedModels"> /// Used for keeping recursive loading from resulting /// in infinite loops. Evaluate each loaded item from /// a database result set against this collection; if /// there is a match, use the collection item, /// otherwise use the database loaded item, deep-load /// it, and add it to this collection. /// </param> /// <returns></returns> public virtual TModel DeepLoadModel <TModel>( DataModelQuery <TModel> query, int?depth, DbTransaction transactionContext, List <DataModel> loadedModels ) where TModel : DataModel { TModel e = LoadModel(query, transactionContext); if (e == null) { return(e); } if (loadedModels == null) { loadedModels = new List <DataModel>(); } if (loadedModels.Contains(e)) { return((TModel)loadedModels[loadedModels.IndexOf(e)]); } foreach (DataModel previouslyLoadedModel in loadedModels) { if (query.GetType().IsGenericType) { Type qt = query.GetType().GetGenericArguments()[0]; if (previouslyLoadedModel.GetType().IsOrInherits(qt) && previouslyLoadedModel.Equals(e) && previouslyLoadedModel is TModel) { return((TModel)previouslyLoadedModel); } } } if (!loadedModels.Contains(e)) { loadedModels.Add(e); } foreach (var fe_kvp in e.EntityMappings.ForeignModelMappings) { if (depth == null || depth > 0) { ForeignDataModelAttribute fe = fe_kvp.Value; Type targetEntityType = fe.TargetMemberType; while (targetEntityType.IsGenericType && targetEntityType.IsOrInherits(typeof(IEnumerable))) { targetEntityType = targetEntityType.GetGenericArguments().Last(); } if (!targetEntityType.IsDataModel()) { targetEntityType = typeof(DataModel <>).MakeGenericType(targetEntityType); } Type subQueryType = typeof(DataModelQuery <>).MakeGenericType(targetEntityType); Relationship relationship = fe.Relationship; if (relationship == Relationship.ManyToMany && string.IsNullOrEmpty(fe.MappingTable)) { relationship = Relationship.OneToMany; } switch (relationship) { case Relationship.OneToOne: case Relationship.ManyToOne: IDataModelQuery subQuery = ((IDataModelQuery)Activator.CreateInstance(subQueryType)) .WhereColumn[fe.RelatedTableColumn].IsEqualTo( e.ColumnMappedValue[fe.LocalColumn]); DataModel e2 = DeepLoadModel(targetEntityType, subQuery, depth == null ? null : depth - 1, transactionContext, loadedModels); object e2o = e2; if (!fe.TargetMemberType.IsDataModel()) { e2o = (e2).Entity; } if (fe.TargetMember.MemberType == MemberTypes.Field) { ((FieldInfo)fe.TargetMember).SetValue(e.Entity, e2o); } else if (fe.TargetMember.MemberType == MemberTypes.Property) { ((PropertyInfo)fe.TargetMember).SetValue(e.Entity, e2o, new object[] {}); } break; case Relationship.OneToMany: IDataModelQuery subQuery2 = ((IDataModelQuery)Activator.CreateInstance(subQueryType)) .WhereColumn[fe.RelatedTableColumn].IsEqualTo( e.ColumnMappedValue[fe.LocalColumn]); IDataModelCollection e2c = DeepLoadModels(targetEntityType, subQuery2, depth, transactionContext, loadedModels); object e2ct = Activator.CreateInstance(fe.TargetMemberType); if (e2ct is IList) { bool de = fe.TargetMemberType.IsGenericType && fe.TargetMemberType.GetGenericArguments().Last().IsDataModel(); foreach (object e2cx in e2c) { if (de) { ((IList)e2ct).Add(e2cx); } else { object e2cx2 = ((DataModel)e2cx).Entity; ((IList)e2ct).Add(e2cx2); } } } else { e2ct = ((IList)e2c)[0]; } if (fe.TargetMember.MemberType == MemberTypes.Field) { ((FieldInfo)fe.TargetMember).SetValue(e.Entity, e2ct); } else if (fe.TargetMember.MemberType == MemberTypes.Property) { ((PropertyInfo)fe.TargetMember).SetValue(e.Entity, e2ct, new object[] {}); } break; case Relationship.ManyToMany: if (!fe.TargetMemberType.IsOrInherits(typeof(IList))) { throw new InvalidCastException( "Cannot apply ManyToMany binding to a non-IList property."); } Type tleft = fe.DeclaringType; Type tleftEntity = tleft; while (tleftEntity.IsDataModelWrapper(true)) { if (tleftEntity.BaseType != (typeof(DataModel <>)).BaseType) { tleftEntity = tleftEntity.BaseType; } else { tleftEntity = tleftEntity.GetGenericArguments()[0]; } } Type tright = (fe.TargetMemberType.IsGenericType && !fe.TargetMemberType.IsDataModel() && fe.TargetMemberType.IsOrInherits(typeof(IList))) ? fe.TargetMemberType.GetGenericArguments()[0] : fe.TargetMemberType; Type trightEntity = tright; if (!tright.IsDataModel()) { tright = typeof(DataModel <>).MakeGenericType(tright); } Type mapType = typeof(DataModelMap.RuntimeMappingTable <,>) .MakeGenericType( // left side of mapping table fe.TargetMember.DeclaringType, // right side tright); var mapObj = (DataModel)Activator.CreateInstance(mapType); mapObj.EntityMappings.TableMapping.Schema = fe.MappingTableSchema ?? ProviderDefaults.DefaultSchema; mapObj.EntityMappings.TableMapping.Table = fe.MappingTable ?? (string.Compare(trightEntity.Name, tleftEntity.Name) == -1 ? trightEntity.Name + tleftEntity.Name : tleftEntity.Name + trightEntity.Name); DataModelColumnAttribute mapLeftCol = mapObj.EntityMappings.FieldMappings["LeftColumn"]; mapLeftCol.ColumnName = fe.LocalColumn; mapLeftCol.DbType = e.EntityMappings .GetFieldMappingByDbColumnName(fe.LocalColumn).DbType; mapLeftCol.TargetMemberType = e.EntityMappings .GetFieldMappingByDbColumnName(fe.LocalColumn).TargetMemberType; Type mapQueryType = typeof(DataModelQuery <>).MakeGenericType(new[] { mapType }); var mapQuery = (IDataModelQuery)Activator.CreateInstance(mapQueryType); mapQuery.WhereColumn[fe.LocalColumn].IsEqualTo( e.ColumnMappedValue[fe.LocalColumn]); IDataModelCollection mapdes = LoadModels(mapType, mapQuery, transactionContext); var mappedDEs = new DataModelCollection <DataModel>(); foreach (DataModel de in mapdes) // de is a MappingTable<L,R> { var mappedDEQuery = (IDataModelQuery) Activator.CreateInstance(typeof(DataModelQuery <>) .MakeGenericType(targetEntityType)); mappedDEQuery.WhereColumn[fe.RelatedTableColumn] .IsEqualTo(de.ColumnMappedValue[fe.RelatedTableColumn]); DataModel mappedDE = DeepLoadModel(targetEntityType, mappedDEQuery, depth == null ? null : depth - 1, transactionContext, loadedModels); if (mappedDE != null) { mappedDEs.Add(mappedDE); } } Type mmtargtype = fe.TargetMemberType; var mmtargcol = (IList)Activator.CreateInstance(fe.TargetMemberType); Type mapdeType = null; foreach (DataModel mapde in mappedDEs) { if (mapdeType == null) { mapdeType = mapde.GetType(); } object deinst = mapde; if (mmtargtype.IsGenericType && !mmtargtype.GetGenericArguments()[0].IsDataModel()) { deinst = mapde.Entity; } mmtargcol.Add(deinst); } if (fe.TargetMember is FieldInfo) { ((FieldInfo)fe.TargetMember).SetValue(e, mmtargcol); } else if (fe.TargetMember is PropertyInfo) { ((PropertyInfo)fe.TargetMember).SetValue( e.Entity, mmtargcol, new object[] {}); } break; } } } foreach (var field_kvp in e.EntityMappings.FieldMappings) { DataModelColumnAttribute field = field_kvp.Value; if (field.IsForeignKey && field.ForeignKeyMapping.AssignToMember != null) { LoadMember(e, field, field_kvp.Key, transactionContext, loadedModels); } } return(e); }