Пример #1
0
        public void TestAdd()
        {
            var changedProperties = new List <string>();

            _model.PropertyChanged += (o, e) => changedProperties.Add(e.PropertyName);

            _model.Add(new TestClass());

            Assert.That(_model.Count, Is.EqualTo(1));
            Assert.That(_model.IsModified, Is.True);
            Assert.That(changedProperties, Has.Member("Count"), "Count may be passed through the view layer for binding and should raise an event.");
            Assert.That(changedProperties, Has.No.Member("IsCollectionChanged"), "IsCollectionChanged is similar to ModelBase.IsModified and should not raise an event.");
        }
Пример #2
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);
        }
Пример #3
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();
                }
            }
        }
Пример #4
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);
            }
        }
Пример #5
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
            }
        }
Пример #6
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);
        }
Пример #7
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("_"));
        }