Exemplo n.º 1
0
        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 }));
        }
Exemplo n.º 2
0
        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 }));
        }
Exemplo n.º 3
0
        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[] {});
            }
        }
Exemplo n.º 4
0
        /// <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);
        }