Пример #1
0
        public void DeepLoadEntityManyToManyTest()
        {
            var usersTable     = CreateAndPopulateMockTable("User");
            var groupsTable    = CreateAndPopulateMockTable("Group");
            var groupUserTable = CreateAndPopulateMockTable("GroupUser");

            var memProvider = new MemoryDataProvider();

            memProvider.AddTable(usersTable);
            memProvider.AddTable(groupsTable);
            memProvider.AddTable(groupUserTable);
            var query   = new DataModelQuery <DataModel <Group> >();
            var egroups = memProvider.DeepLoadModels(query);
            var groups  = new DataModelCollection <DataModel <Group> >(egroups);

            Assert.IsTrue(groups.Count == 2, "Groups did not load");
            Assert.IsNotNull(groups[0].Entity, "Group 0 Entity was not set");
            Assert.IsNotNull(groups[0].Entity.Users, "Group 0 Users were not set");
            Assert.IsTrue(groups[0].Entity.Users.Count == 2, "Users count (group 0 of 0,1) is not 2");
            Assert.IsNotNull(groups[1].Entity, "Group 1 Entity was not set");
            Assert.IsNotNull(groups[0].Entity.Users, "Group 1 Users were not set");
            Assert.IsTrue(groups[1].Entity.Users.Count == 2, "Users count (group 1 of 0,1) is not 2");

            Assert.IsTrue(groups[0].Entity.Users[0].ID
                          != groups[1].Entity.Users[0].ID, "Same user loaded between groups");
            Assert.IsTrue(groups[0].Entity.Users[0].ID
                          != groups[1].Entity.Users[1].ID, "Same user loaded between groups");
            Assert.IsTrue(groups[1].Entity.Users[0].ID
                          != groups[0].Entity.Users[0].ID, "Same user loaded between groups");
        }
 public SampleViewModel()
 {
     Data = new DataModelCollection {
         new DataModel {
             NodeName = "Node 11", Children = new DataModelCollection {
                 new DataModel {
                     NodeName = "Node 113"
                 },
                 new DataModel {
                     NodeName = "Node 123"
                 },
                 new DataModel {
                     NodeName = "Node 133"
                 },
             }
         },
         new DataModel {
             NodeName = "Node 22", Children = new DataModelCollection {
                 new DataModel {
                     NodeName = "Node 213"
                 },
                 new DataModel {
                     NodeName = "Node 223"
                 },
             }
         },
         new DataModel {
             NodeName = "Node 33", Children = new DataModelCollection {
                 new DataModel {
                     NodeName = "Node 313"
                 },
             }
         },
     };
 }
Пример #3
0
        /// <summary>
        /// Saves the changes that were made to each of the
        /// specified <paramref name="dataEntities"/>, within the specified
        /// database <paramref name="transactionContext"/>.
        /// <remarks>
        /// The specified entities must have the Deleted property set to true,
        /// IsDirty evaluated as true, or IsNew evaluated as true, or else
        /// the entity will not be saved.
        /// </remarks>
        /// </summary>
        /// <param name="dataEntities"></param>
        /// <param name="transactionContext"></param>
        public override void SaveModels <TModel>(DataModelCollection <TModel> dataEntities,
                                                 DbTransaction transactionContext)
        {
            DbConnection tmpConn = null;

            if (transactionContext == null)
            {
                tmpConn            = CreateAndOpenConnection();
                transactionContext = tmpConn.BeginTransaction();
            }
            try
            {
                foreach (TModel entity in dataEntities)
                {
                    SaveModel(entity, transactionContext);
                }
            }
            finally
            {
                if (tmpConn != null)
                {
                    transactionContext.Commit();
                    tmpConn.Close();
                }
            }
        }
Пример #4
0
        /// <summary>
        /// Loads the full object graph for the
        /// <see cref="DataModel"/> objects that are 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 DataModelCollection <TModel> DeepLoadModels <TModel>(
            DataModelQuery <TModel> query, int?depth, DbTransaction transactionContext,
            List <DataModel> loadedModels) where TModel : DataModel
        {
            DataModelCollection <TModel> entities = LoadModels(query);
            DataModel e;
            bool      hasForeignKey = false;

            if (entities.Count > 0)
            {
                e = entities[0];
                foreach (var field_kvp in e.EntityMappings.FieldMappings)
                {
                    DataModelColumnAttribute field = field_kvp.Value;
                    if (field.IsForeignKey)
                    {
                        hasForeignKey = true;
                        break;
                    }
                }
                if (!hasForeignKey &&
                    (e.EntityMappings.ForeignModelMappings == null ||
                     e.EntityMappings.ForeignModelMappings.Count == 0))
                {
                    return(entities);
                }
            }
            for (int i = 0; i < entities.Count; i++)
            {
                if (depth == null || depth > 0)
                {
                    TModel entity = entities[i];
                    if (hasForeignKey && !loadedModels.Contains(entity))
                    {
                        foreach (var field_kvp in entity.EntityMappings.FieldMappings)
                        {
                            DataModelColumnAttribute field = field_kvp.Value;
                            if (field.IsForeignKey && field.ForeignKeyMapping.AssignToMember != null)
                            {
                                LoadMember(entity, field, field_kvp.Key,
                                           transactionContext, loadedModels);
                                loadedModels.Add(entity);
                            }
                        }
                    }
                    if (entity.EntityMappings.ForeignModelMappings != null &&
                        entity.EntityMappings.ForeignModelMappings.Count > 0
                        )
                    {
                        DataModelQuery <TModel> query2 = EntityToIdentifyingQuery(entity);
                        entity = (depth == null)
                                     ? DeepLoadModel(query2, transactionContext, loadedModels)
                                     : DeepLoadModel(query2, depth - 1, transactionContext, loadedModels);
                        //loadedModels.Add(entity);
                        entities[i] = entity;
                    }
                }
            }
            return(entities);
        }
Пример #5
0
        /// <summary>
        /// Saves the entire object graph of the specified
        /// <see cref="DataModel"/> objects, within the specified
        /// database <paramref name="transactionContext"/>,
        /// where any of their properties
        /// are also <see cref="DataModel"/> objects with
        /// IsDirty, Deleted, or IsNew change state.
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <param name="col"></param>
        /// <param name="transactionContext"></param>
        public void DeepSaveModels <TModel>(
            DataModelCollection <TModel> col,
            DbTransaction transactionContext)
            where TModel : DataModel
        {
            var savedModels = new List <DataModel>();

            DeepSaveModels(col, transactionContext, savedModels);
        }
Пример #6
0
 /// <summary>
 /// Applies the appropriate changes to the database with respect to
 /// any in-memory <see cref="DataTable"/> records associated with
 /// the specified <paramref name="dataEntities"/>.
 /// The <paramref name="transactionContext"/> parameter is not supported
 /// and must be null.
 /// </summary>
 /// <typeparam name="T"></typeparam>
 /// <param name="dataEntities"></param>
 /// <param name="transactionContext"></param>
 public override void SaveModels <T>(
     DataModelCollection <T> dataEntities,
     DbTransaction transactionContext)
 {
     if (transactionContext != null)
     {
         throw new NotImplementedException("MemoryDataProvider does not support DbTransactions");
     }
     foreach (var dataModel in dataEntities)
     {
         SaveModel(dataModel, transactionContext);
     }
 }
Пример #7
0
 /// <summary>
 /// Saves the entire object graph of the specified
 /// <see cref="DataModel"/> objects, within the specified
 /// database <paramref name="transactionContext"/>,
 /// where any of their properties
 /// are also <see cref="DataModel"/> objects with
 /// IsDirty, Deleted, or IsNew change state.
 /// </summary>
 /// <typeparam name="TModel"></typeparam>
 /// <param name="col"></param>
 /// <param name="transactionContext"></param>
 /// <param name="savedModels"></param>
 public virtual void DeepSaveModels <TModel>(
     DataModelCollection <TModel> col,
     DbTransaction transactionContext,
     List <DataModel> savedModels)
     where TModel : DataModel
 {
     foreach (TModel entity in col)
     {
         if (savedModels.Contains(entity))
         {
             continue;
         }
         entity.SynchronizeFields(SyncTo.FieldMappedData);
         DeepSaveModel(entity, transactionContext);
         savedModels.Add(entity);
     }
 }
Пример #8
0
        /// <summary>
        /// Returns a collection of loaded instances of the specified type using the specified
        /// <paramref name="query"/> and <paramref name="transactionContext"/>.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="query"></param>
        /// <param name="transactionContext"></param>
        /// <returns></returns>
        public override DataModelCollection <T> LoadModels <T>(DataModelQuery <T> query, DbTransaction transactionContext)
        {
            if (transactionContext != null)
            {
                throw new NotImplementedException("MemoryDataProvider does not support DbTransactions");
            }
            var map    = DataModel.GetMapping <T>();
            var table  = Tables[map.TableMapping.Table];
            var rows   = table.Select(QueryToExpression(query), QueryToSortExpression(query));
            var retcol = new DataModelCollection <T>();

            if (rows.Length == 0)
            {
                return(retcol);
            }
            var t = DataModel.GetUnwrappedType(typeof(T));

            foreach (DataRow row in rows)
            {
                T ret;
                while (t.IsGenericType && t.IsOrInherits(typeof(IEnumerable)))
                {
                    t = t.GetGenericArguments().Last();
                }
                if (t != typeof(T))
                {
                    var subret = Activator.CreateInstance(t);
                    var retT   = typeof(DataModel <>).MakeGenericType(t);
                    ret = (T)Activator.CreateInstance(retT, new[] { subret });
                    ret.Load(row);
                    ret.DataProvider = this;
                }
                else
                {
                    ret = (T)Activator.CreateInstance(typeof(T));
                    ret.Load(row);
                    ret.DataProvider = this;
                }
                retcol.Add(ret);
            }
            retcol.DataProvider = this;
            return(retcol);
        }
Пример #9
0
        public void DeepLoadEntitiesTest()
        {
            DataProviderBase mockRepos = new MemoryDataProvider();
            var table = ((MemoryDataProvider)mockRepos).AddTable("mock_table");

            PopulateMockTable(table);
            var table2 = ((MemoryDataProvider)mockRepos).AddTable("mock_table2");

            PopulateMockTable(table2);
            var query = DataModel <DataModelRelationshipMetadataTest.MockPocoChild> .NewQuery();

            DataModelCollection <DataModel <DataModelRelationshipMetadataTest.MockPocoChild> >
            entities = mockRepos.DeepLoadModels(query);

            Assert.IsNotNull(entities);
            Assert.IsTrue(entities.Count == 4);
            Assert.IsTrue(entities[0].Entity.MockPoco != null);
            Assert.IsTrue(entities[3].Entity.MockPoco != null);
            Assert.IsTrue(entities[2].Entity.MockPoco.MockDecimalValue
                          .Equals(entities[2].Entity.MockDecimalValue));
        }
Пример #10
0
 public DataModel()
 {
     Children = new DataModelCollection();
 }
Пример #11
0
        /// <summary>
        /// Loads a set of <see cref="DataModel"/> objects
        /// using the specified <paramref name="query"/> within the
        /// specified database <paramref name="transactionContext"/>.
        /// </summary>
        /// <typeparam name="TModel"></typeparam>
        /// <param name="query"></param>
        /// <param name="transactionContext"></param>
        /// <returns></returns>
        public override DataModelCollection <TModel> LoadModels <TModel>(
            DataModelQuery <TModel> query, DbTransaction transactionContext)
        {
            DataModelMap demap = DataModel.GetMapping <TModel>();

            DbConnection tmpConn = null;

            if (transactionContext == null)
            {
                tmpConn            = CreateAndOpenConnection();
                transactionContext = tmpConn.BeginTransaction(ProviderDefaults.IsolationLevel);
            }
            DbConnection conn = transactionContext.Connection;

            try
            {
                DbDataProviderCommandBuilder <TModel> cmdBuilder = CreateCommandBuilder(query);
                using (DbCommand cmd = cmdBuilder.CreateDbCommand(transactionContext))
                {
                    cmd.Transaction = transactionContext;

                    using (DbDataReader dr = cmd.ExecuteReader(cmdBuilder.ExecuteBehavior ?? CommandBehavior.Default))
                    {
                        var ret = new DataModelCollection <TModel> {
                            DataProvider = this
                        };

                        if (query.Pagination == null ||
                            query.Pagination.ItemsPerPage == int.MaxValue ||
                            query.Pagination.ItemsPerPage == 0 ||
                            cmdBuilder.PaginationIsHandled)
                        {
                            while (dr.Read())
                            {
                                var obj = (TModel)Activator.CreateInstance(typeof(TModel));
                                obj.DataProvider = this;
                                obj.Load(dr);
                                ret.Add(obj);
                            }
                        }
                        else
                        {
                            int start = query.Pagination.Page * query.Pagination.ItemsPerPage -
                                        query.Pagination.ItemsPerPage;
                            bool eof = false;
                            for (int i = 0; i < start; i++)
                            {
                                if (!dr.Read())
                                {
                                    eof = true;
                                    break;
                                }
                            }
                            for (int i = 0; i < query.Pagination.ItemsPerPage && !eof; i++)
                            {
                                if (!dr.Read())
                                {
                                    eof = true;
                                    break;
                                }
                                var obj = (TModel)Activator.CreateInstance(typeof(TModel));
                                obj.DataProvider = this;
                                obj.Load(dr);
                                ret.Add(obj);
                            }
                        }
                        if (!string.IsNullOrEmpty(demap.TableMapping.SelectManyProcedure) &&
                            query.OrderBy.Count > 0)
                        {
                            // exec sort from last sort field to first to get correct end result
                            for (int i = query.OrderBy.Count - 1; i >= 0; i--)
                            {
                                string fld = query.OrderBy[i].GetFieldMapping(typeof(TModel)).TargetMember.Name;
                                switch (query.OrderBy[i].SortDirection)
                                {
                                case Sort.Ascending:
                                    TModel[] asc = (from item in ret
                                                    orderby item[fld] ascending
                                                    select item).ToArray();
                                    ret = new DataModelCollection <TModel>(asc);
                                    break;

                                case Sort.Descending:
                                    TModel[] desc = (from item in ret
                                                     orderby item[fld] descending
                                                     select item).ToArray();
                                    ret = new DataModelCollection <TModel>(desc);
                                    break;
                                }
                            }
                        }
                        return(ret);
                    }
                }
            }
            finally
            {
                if (tmpConn != null)
                {
                    transactionContext.Commit();
                    tmpConn.Close();
                }
            }
        }
Пример #12
0
        public void DeepSaveEntitiesTest()
        {
            var companyTable = CreateAndPopulateMockTable("Company");
            var contactTable = CreateAndPopulateMockTable("Contact");

            var memProvider = new MemoryDataProvider();

            memProvider.AddTable(companyTable);
            memProvider.AddTable(contactTable);

            var query = new DataModelQuery <DataModel <Company> >()
                        .WhereProperty["ID"].IsEqualTo(1);
            var decompany = memProvider.DeepLoadModel(query);
            var company   = decompany.Entity;

            company.CompanyName += "_";
            foreach (var c in company.Contacts)
            {
                c.Name += "_";
            }

            var query2 = new DataModelQuery <DataModel <Company> >()
                         .WhereProperty["ID"].IsEqualTo(2);
            var decompany2 = memProvider.DeepLoadModel(query2);
            var company2   = decompany2.Entity;

            company2.CompanyName = "_" + company2.CompanyName;
            foreach (var c in company2.Contacts)
            {
                c.Name = "_" + c.Name;
            }

            var col = new DataModelCollection <DataModel <Company> >();

            col.Add(decompany);
            col.Add(decompany2);
            col.DataProvider = memProvider;

            col.Save(true);

            query = new DataModelQuery <DataModel <Company> >()
                    .WhereProperty["ID"].IsEqualTo(1);
            decompany = memProvider.DeepLoadModel(query);
            company   = decompany.Entity;
            Assert.IsTrue(company.CompanyName.Length > 1 &&
                          company.CompanyName.EndsWith("_"));
            Assert.IsTrue(company.Contacts[0]
                          .Name.Length > 1 &&
                          company.Contacts[0]
                          .Name.EndsWith("_"));
            Assert.IsTrue(company.Contacts[company.Contacts.Count - 1]
                          .Name.Length > 1 &&
                          company.Contacts[company.Contacts.Count - 1]
                          .Name.EndsWith("_"));

            query = new DataModelQuery <DataModel <Company> >()
                    .WhereProperty["ID"].IsEqualTo(2);
            decompany = memProvider.DeepLoadModel(query);
            company   = decompany.Entity;
            Assert.IsTrue(company.CompanyName.Length > 1 &&
                          company.CompanyName.StartsWith("_"));
            Assert.IsTrue(company.Contacts[0]
                          .Name.Length > 1 &&
                          company.Contacts[0]
                          .Name.StartsWith("_"));
            Assert.IsTrue(company.Contacts[company.Contacts.Count - 1]
                          .Name.Length > 1 &&
                          company.Contacts[company.Contacts.Count - 1]
                          .Name.StartsWith("_"));
        }
Пример #13
0
        public static void Unserialize(
                this XElement element
            ,   DataModelContext context
            ,   IUnserializeErrorReporter reporter
            ,   ref DataModelCollection<string> instance
            )
        {
            instance = new DataModelCollection<string> (context);

            if (element == null)
            {
                return;
            }

            foreach (var subElement in element.Elements (NodeName))
            {
                instance.Add (subElement.Value);
            }
        }
Пример #14
0
 /// <summary>
 /// When implemented, saves the changes that were made to each of the
 /// specified <paramref name="dataModels"/>, within the specified
 /// database <paramref name="transactionContext"/>.
 /// <remarks>
 /// The specified <paramref name="dataModels"/> must have the Deleted
 /// property set to true, IsDirty evaluated as true, or IsNew
 /// evaluated as true, or else the model will not be saved.
 /// </remarks>
 /// </summary>
 /// <param name="dataModels"></param>
 /// <param name="transactionContext"></param>
 public abstract void SaveModels <TModel>(DataModelCollection <TModel> dataModels,
                                          DbTransaction transactionContext) where TModel : DataModel;
Пример #15
0
        public void DeepSaveEntitiesTest()
        {
            try
            {
                var sqlFactory = SqlClientFactory.Instance;
                var dbProvider = new DbDataProvider(sqlFactory, TestSqlConnection);

                var query = new DataModelQuery <DataModel <Company> >()
                            .WhereProperty["ID"] == 1;
                var decompany = dbProvider.DeepLoadModel(query);
                var company   = decompany.Entity;
                company.CompanyName += "_";
                foreach (var c in company.Contacts)
                {
                    c.Name += "_";
                }

                var query2 = new DataModelQuery <DataModel <Company> >()
                             .WhereProperty["ID"] == 2;
                var decompany2 = dbProvider.DeepLoadModel(query2);
                var company2   = decompany2.Entity;
                company2.CompanyName = "_" + company2.CompanyName;
                foreach (var c in company2.Contacts)
                {
                    c.Name = "_" + c.Name;
                }

                var col = new DataModelCollection <DataModel <Company> >();
                col.Add(decompany);
                col.Add(decompany2);
                col.DataProvider = dbProvider;

                col.Save(true);

                query = new DataModelQuery <DataModel <Company> >()
                        .WhereProperty["ID"] == 1;
                decompany = dbProvider.DeepLoadModel(query);
                company   = decompany.Entity;
                Assert.IsTrue(company.CompanyName.Length > 1 &&
                              company.CompanyName.EndsWith("_"));
                Assert.IsTrue(company.Contacts[0]
                              .Name.Length > 1 &&
                              company.Contacts[0]
                              .Name.EndsWith("_"));
                Assert.IsTrue(company.Contacts[company.Contacts.Count - 1]
                              .Name.Length > 1 &&
                              company.Contacts[company.Contacts.Count - 1]
                              .Name.EndsWith("_"));

                query = new DataModelQuery <DataModel <Company> >()
                        .WhereProperty["ID"] == 2;
                decompany = dbProvider.DeepLoadModel(query);
                company   = decompany.Entity;
                Assert.IsTrue(company.CompanyName.Length > 1 &&
                              company.CompanyName.StartsWith("_"));
                Assert.IsTrue(company.Contacts[0]
                              .Name.Length > 1 &&
                              company.Contacts[0]
                              .Name.StartsWith("_"));
                Assert.IsTrue(company.Contacts[company.Contacts.Count - 1]
                              .Name.Length > 1 &&
                              company.Contacts[company.Contacts.Count - 1]
                              .Name.StartsWith("_"));
            }
            finally
            {
                ReloadData_CompanyContact(); // clean-up
            }
        }
Пример #16
0
 public void Setup()
 {
     _model = new DataModelCollection <TestClass>();
 }
Пример #17
0
 /// <summary>
 /// When implemented, saves the changes that were made to each of the
 /// specified <paramref name="dataModels"/>.
 /// </summary>
 /// <typeparam name="TModel"></typeparam>
 /// <param name="dataModels"></param>
 public void SaveModels <TModel>(DataModelCollection <TModel> dataModels) where TModel : DataModel
 {
     SaveModels(dataModels, null);
 }
Пример #18
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);
        }
Пример #19
0
 /// <summary>
 /// Saves the entire object graph of the specified
 /// <see cref="DataModel"/> objects,
 /// where any of their properties
 /// are also <see cref="DataModel"/> objects with
 /// IsDirty, Deleted, or IsNew change state.
 /// </summary>
 /// <typeparam name="TModel"></typeparam>
 /// <param name="col"></param>
 public void DeepSaveModels <TModel>(DataModelCollection <TModel> col) where TModel : DataModel
 {
     DeepSaveModels(col, null);
 }