예제 #1
0
        public void Insert_NonIdentityKey_MatchesExpected()
        {
            var mockDatabaseFactory = new Mock <IDatabaseContextFactory>();
            var mockDatabaseContext = new Mock <IDatabaseContext>();

            mockDatabaseFactory.Setup(factory => factory.Create()).Returns(mockDatabaseContext.Object);

            var repositoryAdapter = new Mock <IRepositoryAdapter>();

            mockDatabaseContext.Setup(context => context.RepositoryAdapter).Returns(repositoryAdapter.Object);

            var definitionProvider = new DataAnnotationsDefinitionProvider();

            repositoryAdapter.Setup(compiler => compiler.CreateInsertionStatement <DependentRow>()).Returns(string.Empty);
            repositoryAdapter.Setup(adapter => adapter.DefinitionProvider).Returns(definitionProvider);

            var databaseFactory = mockDatabaseFactory.Object;

            using (var target = new DatabaseRepositoryProvider(databaseFactory))
            {
                var expected = new DependentRow
                {
                    FakeDependentEntityId = 234,
                    DependentIntegerValue = 4583,
                    DependentTimeValue    = DateTimeOffset.Now
                };

                var actual = target.Insert(expected);
                Assert.AreSame(expected, actual);
            }
        }
예제 #2
0
        /// <summary>
        /// Creates a fake complex row.
        /// </summary>
        /// <param name="withDependentEntity">
        /// A value indicating whether to create the row with a dependent entity.
        /// </param>
        /// <returns>
        /// A new <see cref="ComplexFlatRow"/> instance.
        /// </returns>
        public static ComplexRaisedRow CreateFakeRaisedComplexRow(bool withDependentEntity)
        {
            var createdBy = new MultiReferenceRow {
                Description = MyString, FakeMultiReferenceEntityId = MyInt, UniqueName = MyString
            };
            var fakeSubSubEntity = new SubSubRow {
                FakeSubSubEntityId = MyInt, UniqueName = MyString, Description = MyString
            };
            var fakeSubEntity = new SubRow
            {
                FakeSubEntityId    = MyInt,
                FakeSubSubEntityId = MyInt,
                SubSubEntity       = fakeSubSubEntity,
                UniqueName         = MyString,
                UniqueOtherId      = MyShort,
                Description        = MyString
            };

            var modifiedBy = new MultiReferenceRow {
                FakeMultiReferenceEntityId = MyInt, Description = MyString, UniqueName = MyString
            };

            var fakeDependentEntity = new DependentRow
            {
                FakeDependentEntityId = MyInt,
                DependentIntegerValue = MyInt,
                DependentTimeValue    = MyDateTimeOffset
            };

            return(new ComplexRaisedRow
            {
                CreatedBy = createdBy,
                UniqueName = MyString,
                FakeSubEntityId = MyInt,
                SubEntity = fakeSubEntity,
                ModifiedBy = modifiedBy,
                DependentEntity = withDependentEntity ? fakeDependentEntity : null,
                ModifiedTime = MyDateTimeOffset,
                Description = MyString,
                FakeEnumerationId = MyInt,
                CreationTime = MyDateTimeOffset,
                FakeOtherEnumerationId = MyInt,
                ComplexEntityId = MyInt
            });
        }
예제 #3
0
        public void Load_ListOfRows_DataMatchesExpected()
        {
            var target        = new DataTableLoader <DependentRow>(new DataAnnotationsDefinitionProvider());
            var dependentRows = new List <DependentRow>
            {
                new DependentRow
                {
                    FakeDependentEntityId = 454, DependentIntegerValue = 3, DependentTimeValue = DateTimeOffset.MaxValue
                },
                new DependentRow
                {
                    FakeDependentEntityId = 455, DependentIntegerValue = 2, DependentTimeValue = DateTimeOffset.MinValue
                },
                new DependentRow
                {
                    FakeDependentEntityId = 456, DependentIntegerValue = 1, DependentTimeValue = DateTimeOffset.Now
                },
                new DependentRow
                {
                    FakeDependentEntityId = 457, DependentIntegerValue = 1, DependentTimeValue = DateTimeOffset.Now
                },
                new DependentRow
                {
                    FakeDependentEntityId = 458, DependentIntegerValue = 3, DependentTimeValue = DateTimeOffset.MaxValue
                }
            };

            var actual = target.Load(dependentRows);

            Assert.AreEqual(dependentRows.Count, actual.Rows.Count);

            for (int i = 0; i < dependentRows.Count; i++)
            {
                var actualRow = new DependentRow
                {
                    FakeDependentEntityId = (int)actual.Rows[i][nameof(DependentRow.FakeDependentEntityId)],
                    DependentIntegerValue = (int)actual.Rows[i][nameof(DependentRow.DependentIntegerValue)],
                    DependentTimeValue    = (DateTimeOffset)actual.Rows[i][nameof(DependentRow.DependentTimeValue)]
                };

                Assert.AreEqual(dependentRows.ElementAt(i), actualRow);
            }
        }
예제 #4
0
 /// <summary>
 /// Register a dependency for this row.
 /// </summary>
 public void AddChild(DependentRow childRow)
 {
     this.ChildRows.Add(childRow);
     childRow.ParentRows.Add(this);
 }
예제 #5
0
        public DbImportTool Import(ISimpleTaskHost host, DataSet data, DbConnection connection, DbTransaction transaction)
        {
            // Collections of actions:
            var toImport = new Queue<DependentRow>();
            var toImportPerTable = new Dictionary<string, List<DependentRow>>();
            var toUpdate = new Queue<DependentUpdate>();
            var sqlUpdateCmds = new Dictionary<string, DbCommand>();
            sqlUpdateCmds["IDENTITY"] = connection.CreateCommand("SELECT @@IDENTITY", CommandType.Text, transaction);

            // Change identity column values to negative to avoid conflicts on destination database:
            foreach (DataTable table in data.Tables)
            {
                foreach (DataColumn col in table.Columns)
                {
                    if (col.AutoIncrement)
                    {
                        col.ReadOnly = false;
                        foreach (DataRow row in table.Rows)
                        {
                            row[col] = -(int)row[col];
                        }
                    }
                }
            }

            // Read all rows:
            foreach (DataTable table in data.Tables)
            {
                var perTable = toImportPerTable[table.TableName] = new List<DependentRow>();
                foreach (DataRow row in table.Rows)
                {
                    var drow = new DependentRow() { Row = row };
                    toImport.Enqueue(drow);
                    perTable.Add(drow);
                }
            }

            host.Out.WriteLine("Importing {0} data rows...", toImport.Count);

            // Connect row dependencies:
            foreach (DataRelation relation in data.Relations)
            {
                // TODO: Should also include rows with non-AutoIncrement Primary Keys and multi-column Primary Keys.

                // Ignore relations where primary key is not an AutoIncrement field:
                if (relation.ParentColumns.Count() != 1 || !relation.ParentColumns[0].AutoIncrement) continue;

                var parentColumn = relation.ParentColumns[0];
                var childColumn = relation.ChildColumns[0];

                if (childColumn.AllowDBNull)
                {
                    // If foreign key is nullable, make it null and register a delayed update:
                    foreach (var parentRow in toImportPerTable[relation.ParentTable.TableName])
                    {
                        var parentPkValue = parentRow.Row[parentColumn];
                        foreach (var childRow in toImportPerTable[relation.ChildTable.TableName].Where(dr => Object.Equals(dr.Row[childColumn], parentPkValue)))
                        {
                            toUpdate.Enqueue(new DependentUpdate() { Row = childRow.Row, Column = childColumn, SourceRow = parentRow.Row, SourceColumn = parentColumn });
                            childRow.Row[childColumn] = DBNull.Value;
                        }
                    }
                }
                else
                {
                    // If foreign key row is not nullable, register dependency:
                    foreach (var parentRow in toImportPerTable[relation.ParentTable.TableName])
                    {
                        var parentPkValue = parentRow.Row[parentColumn];
                        foreach (var childRow in toImportPerTable[relation.ChildTable.TableName].Where(dr => Object.Equals(dr.Row[childColumn], parentPkValue)))
                        {
                            parentRow.AddChild(childRow);
                        }
                    }
                }
            }

            var totalActions = (double)(toImport.Count + toUpdate.Count);
            
            // Import rows:
            while (toImport.Count > 0)
            {
                var drow = toImport.Dequeue();
                if (drow.HasAllDependenciesResolved)
                {
                    drow.WriteToDatabase(host, connection, transaction, sqlUpdateCmds);
                    drow.MarkResolved();
                }
                else
                {
                    //Console.WriteLine("SKIPPED : {0} ({1})", drow.Row.Table.TableName, String.Join(", ", drow.Values().Take(1).Select(v => (v ?? "##null").ToString())));
                    toImport.Enqueue(drow);
                }

                host.ReportProgress((totalActions - toImport.Count - toUpdate.Count) / totalActions, drow.Row.Table.TableName);
            }

            // Dispose commands:
            sqlUpdateCmds.Values.ToList().ForEach(cmd => cmd.Dispose());

            host.Out.WriteLine("\r\nUpdating {0} data rows...", toUpdate.Count);

            // Perform delayed updates:
            using(var cmd = connection.CreateCommand())
            {
                cmd.Transaction = transaction;

                cmd.AddParameter("@SourceValue", null);
                cmd.AddParameter("@PkValue", null);
                
                while (toUpdate.Count > 0)
                {
                    var dupdate = toUpdate.Dequeue();
                    dupdate.WriteToDatabase(host, connection, cmd);

                    host.ReportProgress((totalActions - toImport.Count - toUpdate.Count) / totalActions, dupdate.Row.Table.TableName);
                }
            }

            host.Out.WriteLine();

            return this;
        }
예제 #6
0
 /// <summary>
 /// Register a dependency for this row.
 /// </summary>
 public void AddChild(DependentRow childRow)
 {
     this.ChildRows.Add(childRow);
     childRow.ParentRows.Add(this);
 }
예제 #7
0
        public DbImportTool Import(ISimpleTaskHost host, DataSet data, DbConnection connection, DbTransaction transaction)
        {
            // Collections of actions:
            var toImport         = new Queue <DependentRow>();
            var toImportPerTable = new Dictionary <string, List <DependentRow> >();
            var toUpdate         = new Queue <DependentUpdate>();
            var sqlUpdateCmds    = new Dictionary <string, DbCommand>();

            sqlUpdateCmds["IDENTITY"] = connection.CreateCommand("SELECT @@IDENTITY", CommandType.Text, transaction);

            // Change identity column values to negative to avoid conflicts on destination database:
            foreach (DataTable table in data.Tables)
            {
                foreach (DataColumn col in table.Columns)
                {
                    if (col.AutoIncrement)
                    {
                        col.ReadOnly = false;
                        foreach (DataRow row in table.Rows)
                        {
                            row[col] = -(int)row[col];
                        }
                    }
                }
            }

            // Read all rows:
            foreach (DataTable table in data.Tables)
            {
                var perTable = toImportPerTable[table.TableName] = new List <DependentRow>();
                foreach (DataRow row in table.Rows)
                {
                    var drow = new DependentRow()
                    {
                        Row = row
                    };
                    toImport.Enqueue(drow);
                    perTable.Add(drow);
                }
            }

            host.Out.WriteLine("Importing {0} data rows...", toImport.Count);

            // Connect row dependencies:
            foreach (DataRelation relation in data.Relations)
            {
                // TODO: Should also include rows with non-AutoIncrement Primary Keys and multi-column Primary Keys.

                // Ignore relations where primary key is not an AutoIncrement field:
                if (relation.ParentColumns.Count() != 1 || !relation.ParentColumns[0].AutoIncrement)
                {
                    continue;
                }

                var parentColumn = relation.ParentColumns[0];
                var childColumn  = relation.ChildColumns[0];

                if (childColumn.AllowDBNull)
                {
                    // If foreign key is nullable, make it null and register a delayed update:
                    foreach (var parentRow in toImportPerTable[relation.ParentTable.TableName])
                    {
                        var parentPkValue = parentRow.Row[parentColumn];
                        foreach (var childRow in toImportPerTable[relation.ChildTable.TableName].Where(dr => Object.Equals(dr.Row[childColumn], parentPkValue)))
                        {
                            toUpdate.Enqueue(new DependentUpdate()
                            {
                                Row = childRow.Row, Column = childColumn, SourceRow = parentRow.Row, SourceColumn = parentColumn
                            });
                            childRow.Row[childColumn] = DBNull.Value;
                        }
                    }
                }
                else
                {
                    // If foreign key row is not nullable, register dependency:
                    foreach (var parentRow in toImportPerTable[relation.ParentTable.TableName])
                    {
                        var parentPkValue = parentRow.Row[parentColumn];
                        foreach (var childRow in toImportPerTable[relation.ChildTable.TableName].Where(dr => Object.Equals(dr.Row[childColumn], parentPkValue)))
                        {
                            parentRow.AddChild(childRow);
                        }
                    }
                }
            }

            var totalActions = (double)(toImport.Count + toUpdate.Count);

            // Import rows:
            while (toImport.Count > 0)
            {
                var drow = toImport.Dequeue();
                if (drow.HasAllDependenciesResolved)
                {
                    drow.WriteToDatabase(host, connection, transaction, sqlUpdateCmds);
                    drow.MarkResolved();
                }
                else
                {
                    //Console.WriteLine("SKIPPED : {0} ({1})", drow.Row.Table.TableName, String.Join(", ", drow.Values().Take(1).Select(v => (v ?? "##null").ToString())));
                    toImport.Enqueue(drow);
                }

                host.ReportProgress((totalActions - toImport.Count - toUpdate.Count) / totalActions, drow.Row.Table.TableName);
            }

            // Dispose commands:
            sqlUpdateCmds.Values.ToList().ForEach(cmd => cmd.Dispose());

            host.Out.WriteLine("\r\nUpdating {0} data rows...", toUpdate.Count);

            // Perform delayed updates:
            using (var cmd = connection.CreateCommand())
            {
                cmd.Transaction = transaction;

                cmd.AddParameter("@SourceValue", null);
                cmd.AddParameter("@PkValue", null);

                while (toUpdate.Count > 0)
                {
                    var dupdate = toUpdate.Dequeue();
                    dupdate.WriteToDatabase(host, connection, cmd);

                    host.ReportProgress((totalActions - toImport.Count - toUpdate.Count) / totalActions, dupdate.Row.Table.TableName);
                }
            }

            host.Out.WriteLine();

            return(this);
        }