Inheritance: INameable, IHasOwner, IScriptable
コード例 #1
0
ファイル: ForeignKeyTester.cs プロジェクト: Zocdoc/schemazen
		public void TestMultiColumnKey() {
			var t1 = new Table("dbo", "t1");
			t1.Columns.Add(new Column("c2", "varchar", 10, false, null));
			t1.Columns.Add(new Column("c1", "int", false, null));
			t1.AddConstraint(new Constraint("pk_t1", "PRIMARY KEY", "c1,c2"));

			var t2 = new Table("dbo", "t2");
			t2.Columns.Add(new Column("c1", "int", false, null));
			t2.Columns.Add(new Column("c2", "varchar", 10, false, null));
			t2.Columns.Add(new Column("c3", "int", false, null));

			var fk = new ForeignKey(t2, "fk_test", "c3,c2", t1, "c1,c2");

			var db = new Database("TESTDB");
			db.Tables.Add(t1);
			db.Tables.Add(t2);
			db.ForeignKeys.Add(fk);
			db.Connection = TestHelper.GetConnString("TESTDB");
			db.ExecCreate(true);
			db.Load();

			Assert.AreEqual("c3", db.FindForeignKey("fk_test", "dbo").Columns[0]);
			Assert.AreEqual("c2", db.FindForeignKey("fk_test", "dbo").Columns[1]);
			Assert.AreEqual("c1", db.FindForeignKey("fk_test", "dbo").RefColumns[0]);
			Assert.AreEqual("c2", db.FindForeignKey("fk_test", "dbo").RefColumns[1]);

			db.ExecCreate(true);
		}
コード例 #2
0
ファイル: ForeignKeyTester.cs プロジェクト: Zocdoc/schemazen
		public void TestScript() {
			var person = new Table("dbo", "Person");
			person.Columns.Add(new Column("id", "int", false, null));
			person.Columns.Add(new Column("name", "varchar", 50, false, null));
			person.Columns.Find("id").Identity = new Identity(1, 1);
			person.AddConstraint(new Constraint("PK_Person", "PRIMARY KEY", "id"));

			var address = new Table("dbo", "Address");
			address.Columns.Add(new Column("id", "int", false, null));
			address.Columns.Add(new Column("personId", "int", false, null));
			address.Columns.Add(new Column("street", "varchar", 50, false, null));
			address.Columns.Add(new Column("city", "varchar", 50, false, null));
			address.Columns.Add(new Column("state", "char", 2, false, null));
			address.Columns.Add(new Column("zip", "varchar", 5, false, null));
			address.Columns.Find("id").Identity = new Identity(1, 1);
			address.AddConstraint(new Constraint("PK_Address", "PRIMARY KEY", "id"));

			var fk = new ForeignKey(address, "FK_Address_Person", "personId", person, "id", "", "CASCADE");

			TestHelper.ExecSql(person.ScriptCreate(), "");
			TestHelper.ExecSql(address.ScriptCreate(), "");
			TestHelper.ExecSql(fk.ScriptCreate(), "");
			TestHelper.ExecSql("drop table Address", "");
			TestHelper.ExecSql("drop table Person", "");
		}
コード例 #3
0
ファイル: ForeignKey.cs プロジェクト: Zocdoc/schemazen
		public ForeignKey(Table table, string name, string columns, Table refTable, string refColumns, string onUpdate,
			string onDelete) {
			Table = table;
			Name = name;
			Columns = new List<string>(columns.Split(','));
			RefTable = refTable;
			RefColumns = new List<string>(refColumns.Split(','));
			OnUpdate = onUpdate;
			OnDelete = onDelete;
		}
コード例 #4
0
ファイル: TableTester.cs プロジェクト: Zocdoc/schemazen
		public void CompareConstraints() {

			var t1 = new Table("dbo", "Test");
			var t2 = new Table("dbo", "Test");
			var diff = default(TableDiff);

			//test equal
			t1.Columns.Add(new Column("first", "varchar", 30, false, null));
			t2.Columns.Add(new Column("first", "varchar", 30, false, null));
			t1.AddConstraint(Constraint.CreateCheckedConstraint("IsTomorrow", true, "fnTomorrow()"));
			t2.AddConstraint(Constraint.CreateCheckedConstraint("IsTomorrow", false, "Tomorrow <> 1"));

			diff = t1.Compare(t2);
			Assert.AreEqual(1, diff.ConstraintsChanged.Count);
			Assert.IsNotNull(diff);
			Assert.IsTrue(diff.IsDiff);

		}
コード例 #5
0
ファイル: TableTester.cs プロジェクト: Zocdoc/schemazen
		public void TestCompare() {
			var t1 = new Table("dbo", "Test");
			var t2 = new Table("dbo", "Test");
			var diff = default(TableDiff);

			//test equal
			t1.Columns.Add(new Column("first", "varchar", 30, false, null));
			t2.Columns.Add(new Column("first", "varchar", 30, false, null));
			t1.AddConstraint(new Constraint("PK_Test", "PRIMARY KEY", "first"));
			t2.AddConstraint(new Constraint("PK_Test", "PRIMARY KEY", "first"));

			diff = t1.Compare(t2);
			Assert.IsNotNull(diff);
			Assert.IsFalse(diff.IsDiff);

			//test add
			t1.Columns.Add(new Column("second", "varchar", 30, false, null));
			diff = t1.Compare(t2);
			Assert.IsTrue(diff.IsDiff);
			Assert.AreEqual(1, diff.ColumnsAdded.Count);

			//test delete
			diff = t2.Compare(t1);
			Assert.IsTrue(diff.IsDiff);
			Assert.AreEqual(1, diff.ColumnsDropped.Count);

			//test diff
			t1.Columns.Items[0].Length = 20;
			diff = t1.Compare(t2);
			Assert.IsTrue(diff.IsDiff);
			Assert.AreEqual(1, diff.ColumnsDiff.Count);

			Console.WriteLine("--- create ----");
			Console.Write(t1.ScriptCreate());

			Console.WriteLine("--- migrate up ---");
			Console.Write(t1.Compare(t2).Script());

			Console.WriteLine("--- migrate down ---");
			Console.Write(t2.Compare(t1).Script());
		}
コード例 #6
0
ファイル: ProcTester.cs プロジェクト: Zocdoc/schemazen
		public void TestScript() {
			var t = new Table("dbo", "Address");
			t.Columns.Add(new Column("id", "int", false, null));
			t.Columns.Add(new Column("street", "varchar", 50, false, null));
			t.Columns.Add(new Column("city", "varchar", 50, false, null));
			t.Columns.Add(new Column("state", "char", 2, false, null));
			t.Columns.Add(new Column("zip", "char", 5, false, null));
			t.AddConstraint(new Constraint("PK_Address", "PRIMARY KEY", "id"));

			var getAddress = new Routine("dbo", "GetAddress", null);
			getAddress.Text = @"
CREATE PROCEDURE [dbo].[GetAddress]
	@id int
AS
	select * from Address where id = @id
";

			TestHelper.ExecSql(t.ScriptCreate(), "");
			TestHelper.ExecBatchSql(getAddress.ScriptCreate() + "\nGO", "");

			TestHelper.ExecSql("drop table [dbo].[Address]", "");
			TestHelper.ExecSql("drop procedure [dbo].[GetAddress]", "");
		}
コード例 #7
0
ファイル: Table.cs プロジェクト: Zocdoc/schemazen
		public TableDiff Compare(Table t) {
			var diff = new TableDiff();
			diff.Owner = t.Owner;
			diff.Name = t.Name;

			//get additions and compare mutual columns
			foreach (var c in Columns.Items) {
				var c2 = t.Columns.Find(c.Name);
				if (c2 == null) {
					diff.ColumnsAdded.Add(c);
				} else {
					//compare mutual columns
					var cDiff = c.Compare(c2);
					if (cDiff.IsDiff) {
						diff.ColumnsDiff.Add(cDiff);
					}
				}
			}

			//get deletions
			foreach (var c in t.Columns.Items.Where(c => Columns.Find(c.Name) == null)) {
				diff.ColumnsDropped.Add(c);
			}

			if (!t.IsType) {
				//get added and compare mutual constraints
				foreach (var c in Constraints) {
					var c2 = t.FindConstraint(c.Name);
					if (c2 == null) {
						diff.ConstraintsAdded.Add(c);
					} else {
						if (c.ScriptCreate() != c2.ScriptCreate()) {
							diff.ConstraintsChanged.Add(c);
						}
					}
				}
				//get deleted constraints
				foreach (var c in t.Constraints.Where(c => FindConstraint(c.Name) == null)){
					diff.ConstraintsDeleted.Add(c);
				}
			} else {
				// compare constraints on table types, which can't be named in the script, but have names in the DB
				var dest = Constraints.ToList();
				var src = t.Constraints.ToList();

				var j = from c1 in dest
						join c2 in src on c1.ScriptCreate() equals c2.ScriptCreate() into match //new { c1.Type, c1.Unique, c1.Clustered, Columns = string.Join(",", c1.Columns.ToArray()), IncludedColumns = string.Join(",", c1.IncludedColumns.ToArray()) } equals new { c2.Type, c2.Unique, c2.Clustered, Columns = string.Join(",", c2.Columns.ToArray()), IncludedColumns = string.Join(",", c2.IncludedColumns.ToArray()) } into match
						from m in match.DefaultIfEmpty()
						select new { c1, m };

				foreach (var c in j) {
					if (c.m == null) {
						diff.ConstraintsAdded.Add(c.c1);
					} else {
						src.Remove(c.m);
					}
				}
				foreach (var c in src) {
					diff.ConstraintsDeleted.Add(c);
				}
			}

			return diff;
		}
コード例 #8
0
ファイル: ForeignKey.cs プロジェクト: Zocdoc/schemazen
		public ForeignKey(Table table, string name, string columns, Table refTable, string refColumns)
			: this(table, name, columns, refTable, refColumns, "", "") { }
コード例 #9
0
ファイル: TableTester.cs プロジェクト: Zocdoc/schemazen
		public void TestExportData() {
			var t = new Table("dbo", "Status");
			t.Columns.Add(new Column("id", "int", false, null));
			t.Columns.Add(new Column("code", "char", 1, false, null));
			t.Columns.Add(new Column("description", "varchar", 20, false, null));
			t.Columns.Find("id").Identity = new Identity(1, 1);
			t.AddConstraint(new Constraint("PK_Status", "PRIMARY KEY", "id"));

			var conn = TestHelper.GetConnString("TESTDB");
			DBHelper.DropDb(conn);
			DBHelper.CreateDb(conn);
			SqlConnection.ClearAllPools();
			DBHelper.ExecBatchSql(conn, t.ScriptCreate());

			var dataIn =
				@"1	R	Ready
2	P	Processing
3	F	Frozen
";
			var filename = Path.GetTempFileName();

			var writer = File.AppendText(filename);
			writer.Write(dataIn);
			writer.Flush();
			writer.Close();

			t.ImportData(conn, filename);
			var sw = new StringWriter();
			t.ExportData(conn, sw);
			Assert.AreEqual(dataIn, sw.ToString());

			File.Delete(filename);
		}
コード例 #10
0
ファイル: TableTester.cs プロジェクト: Zocdoc/schemazen
		public void TestScriptNonSupportedColumn() {
			var t = new Table("dbo", "bla");
			t.Columns.Add(new Column("a", "madeuptype", true, null));
			t.ScriptCreate();
		}
コード例 #11
0
ファイル: TableTester.cs プロジェクト: Zocdoc/schemazen
		public void TestScript() {
			//create a table with all known types, script it, and execute the script
			var t = new Table("dbo", "AllTypesTest");
			t.Columns.Add(new Column("a", "bigint", false, null));
			t.Columns.Add(new Column("b", "binary", 50, false, null));
			t.Columns.Add(new Column("c", "bit", false, null));
			t.Columns.Add(new Column("d", "char", 10, false, null));
			t.Columns.Add(new Column("e", "datetime", false, null));
			t.Columns.Add(new Column("f", "decimal", 18, 0, false, null));
			t.Columns.Add(new Column("g", "float", false, null));
			t.Columns.Add(new Column("h", "image", false, null));
			t.Columns.Add(new Column("i", "int", false, null));
			t.Columns.Add(new Column("j", "money", false, null));
			t.Columns.Add(new Column("k", "nchar", 10, false, null));
			t.Columns.Add(new Column("l", "ntext", false, null));
			t.Columns.Add(new Column("m", "numeric", 18, 0, false, null));
			t.Columns.Add(new Column("n", "nvarchar", 50, false, null));
			t.Columns.Add(new Column("o", "nvarchar", -1, false, null));
			t.Columns.Add(new Column("p", "real", false, null));
			t.Columns.Add(new Column("q", "smalldatetime", false, null));
			t.Columns.Add(new Column("r", "smallint", false, null));
			t.Columns.Add(new Column("s", "smallmoney", false, null));
			t.Columns.Add(new Column("t", "sql_variant", false, null));
			t.Columns.Add(new Column("u", "text", false, null));
			t.Columns.Add(new Column("v", "timestamp", false, null));
			t.Columns.Add(new Column("w", "tinyint", false, null));
			t.Columns.Add(new Column("x", "uniqueidentifier", false, null));
			t.Columns.Add(new Column("y", "varbinary", 50, false, null));
			t.Columns.Add(new Column("z", "varbinary", -1, false, null));
			t.Columns.Add(new Column("aa", "varchar", 50, true, new Default("DF_AllTypesTest_aa", "'asdf'")));
			t.Columns.Add(new Column("bb", "varchar", -1, true, null));
			t.Columns.Add(new Column("cc", "xml", true, null));
			t.Columns.Add(new Column("dd", "hierarchyid", false, null));

			Console.WriteLine(t.ScriptCreate());
			TestHelper.ExecSql(t.ScriptCreate(), "");
			TestHelper.ExecSql("drop table [dbo].[AllTypesTest]", "");
		}
コード例 #12
0
ファイル: TableTester.cs プロジェクト: Zocdoc/schemazen
		public void TestLargeAmountOfRowsImportAndExport() {
			var t = new Table("dbo", "TestData");
			t.Columns.Add(new Column("test_field", "int", false, null));
			t.AddConstraint(new Constraint("PK_TestData", "PRIMARY KEY", "test_field"));
			t.AddConstraint(new Constraint("IX_TestData_PK", "INDEX", "test_field") { Clustered = true, Table = t, Unique = true }); // clustered index is required to ensure the row order is the same as what we import

			var conn = TestHelper.GetConnString("TESTDB");
			DBHelper.DropDb(conn);
			DBHelper.CreateDb(conn);
			SqlConnection.ClearAllPools();
			DBHelper.ExecBatchSql(conn, t.ScriptCreate());

			var filename = Path.GetTempFileName();

			var writer = File.CreateText(filename);
			StringBuilder sb = new StringBuilder();

			for (var i = 0; i < Table.rowsInBatch * 4.2; i++) {
				sb.AppendLine(i.ToString());
				writer.WriteLine(i.ToString());
			}

			writer.Flush();
			writer.Close();

			var dataIn = sb.ToString();
			Assert.AreEqual(dataIn, File.ReadAllText(filename)); // just prove that the file and the string are the same, to make the next assertion meaningful!

			try {
				t.ImportData(conn, filename);
				var sw = new StringWriter();
				t.ExportData(conn, sw);

				Assert.AreEqual(dataIn, sw.ToString());
			} finally {
				File.Delete(filename);
			}
		}
コード例 #13
0
ファイル: DatabaseTester.cs プロジェクト: sethreno/schemazen
        public void TestScriptToDir()
        {
            var policy = new Table("dbo", "Policy");
            policy.Columns.Add(new Column("id", "int", false, null) {Position = 1});
            policy.Columns.Add(new Column("form", "tinyint", false, null) {Position = 2});
            policy.AddConstraint(new Constraint("PK_Policy", "PRIMARY KEY", "id") { Clustered = true, Unique = true });
            policy.Columns.Items[0].Identity = new Identity(1, 1);

            var loc = new Table("dbo", "Location");
            loc.Columns.Add(new Column("id", "int", false, null) {Position = 1});
            loc.Columns.Add(new Column("policyId", "int", false, null) {Position = 2});
            loc.Columns.Add(new Column("storage", "bit", false, null) {Position = 3});
            loc.Columns.Add(new Column("category", "int", false, null) { Position = 4 });
            loc.AddConstraint(new Constraint("PK_Location", "PRIMARY KEY", "id") { Clustered = true, Unique = true });
            loc.Columns.Items[0].Identity = new Identity(1, 1);

            var formType = new Table("dbo", "FormType");
            formType.Columns.Add(new Column("code", "tinyint", false, null) {Position = 1});
            formType.Columns.Add(new Column("desc", "varchar", 10, false, null) {Position = 2});
            formType.AddConstraint(new Constraint("PK_FormType", "PRIMARY KEY", "code") { Clustered = true, Unique = true });
            formType.AddConstraint(Constraint.CreateCheckedConstraint("CK_FormType", false, "([code]<(5))"));

            var categoryType = new Table("dbo", "CategoryType");
            categoryType.Columns.Add(new Column("id", "int", false, null) { Position = 1 });
            categoryType.Columns.Add(new Column("Category", "varchar", 10, false, null) { Position = 2 });
            categoryType.AddConstraint(new Constraint("PK_CategoryType", "PRIMARY KEY", "id") { Clustered = true, Unique = true });

            var emptyTable = new Table("dbo", "EmptyTable");
            emptyTable.Columns.Add(new Column("code", "tinyint", false, null) {Position = 1});
            emptyTable.AddConstraint(new Constraint("PK_EmptyTable", "PRIMARY KEY", "code") {Clustered = true, Unique = true});

            var fk_policy_formType = new ForeignKey("FK_Policy_FormType");
            fk_policy_formType.Table = policy;
            fk_policy_formType.Columns.Add("form");
            fk_policy_formType.RefTable = formType;
            fk_policy_formType.RefColumns.Add("code");
            fk_policy_formType.OnUpdate = "NO ACTION";
            fk_policy_formType.OnDelete = "NO ACTION";

            var fk_location_policy = new ForeignKey("FK_Location_Policy");
            fk_location_policy.Table = loc;
            fk_location_policy.Columns.Add("policyId");
            fk_location_policy.RefTable = policy;
            fk_location_policy.RefColumns.Add("id");
            fk_location_policy.OnUpdate = "NO ACTION";
            fk_location_policy.OnDelete = "CASCADE";

            var fk_location_category = new ForeignKey("FK_Location_category");
            fk_location_category.Table = loc;
            fk_location_category.Columns.Add("category");
            fk_location_category.RefTable = categoryType;
            fk_location_category.RefColumns.Add("id");
            fk_location_category.OnUpdate = "NO ACTION";
            fk_location_category.OnDelete = "CASCADE";

            var tt_codedesc = new Table("dbo", "CodeDesc");
            tt_codedesc.IsType = true;
            tt_codedesc.Columns.Add(new Column("code", "tinyint", false, null) { Position = 1 });
            tt_codedesc.Columns.Add(new Column("desc", "varchar", 10, false, null) { Position = 2 });
            tt_codedesc.AddConstraint(new Constraint("PK_CodeDesc", "PRIMARY KEY", "code"));

            var db = new Database("ScriptToDirTest");
            db.Tables.Add(policy);
            db.Tables.Add(formType);
            db.Tables.Add(categoryType);
            db.Tables.Add(emptyTable);
            db.Tables.Add(loc);
            db.TableTypes.Add(tt_codedesc);
            db.ForeignKeys.Add(fk_policy_formType);
            db.ForeignKeys.Add(fk_location_policy);
            db.ForeignKeys.Add(fk_location_category);
            db.FindProp("COMPATIBILITY_LEVEL").Value = "110";
            db.FindProp("COLLATE").Value = "SQL_Latin1_General_CP1_CI_AS";
            db.FindProp("AUTO_CLOSE").Value = "OFF";
            db.FindProp("AUTO_SHRINK").Value = "ON";
            db.FindProp("ALLOW_SNAPSHOT_ISOLATION").Value = "ON";
            db.FindProp("READ_COMMITTED_SNAPSHOT").Value = "OFF";
            db.FindProp("RECOVERY").Value = "SIMPLE";
            db.FindProp("PAGE_VERIFY").Value = "CHECKSUM";
            db.FindProp("AUTO_CREATE_STATISTICS").Value = "ON";
            db.FindProp("AUTO_UPDATE_STATISTICS").Value = "ON";
            db.FindProp("AUTO_UPDATE_STATISTICS_ASYNC").Value = "ON";
            db.FindProp("ANSI_NULL_DEFAULT").Value = "ON";
            db.FindProp("ANSI_NULLS").Value = "ON";
            db.FindProp("ANSI_PADDING").Value = "ON";
            db.FindProp("ANSI_WARNINGS").Value = "ON";
            db.FindProp("ARITHABORT").Value = "ON";
            db.FindProp("CONCAT_NULL_YIELDS_NULL").Value = "ON";
            db.FindProp("NUMERIC_ROUNDABORT").Value = "ON";
            db.FindProp("QUOTED_IDENTIFIER").Value = "ON";
            db.FindProp("RECURSIVE_TRIGGERS").Value = "ON";
            db.FindProp("CURSOR_CLOSE_ON_COMMIT").Value = "ON";
            db.FindProp("CURSOR_DEFAULT").Value = "LOCAL";
            db.FindProp("TRUSTWORTHY").Value = "ON";
            db.FindProp("DB_CHAINING").Value = "ON";
            db.FindProp("PARAMETERIZATION").Value = "FORCED";
            db.FindProp("DATE_CORRELATION_OPTIMIZATION").Value = "ON";

            db.Connection = ConfigHelper.TestDB.Replace("database=TESTDB", "database=" + db.Name);
            db.ExecCreate(true);

            DBHelper.ExecSql(db.Connection,
                "  insert into formType ([code], [desc]) values (1, 'DP-1')\n"
                + "insert into formType ([code], [desc]) values (2, 'DP-2')\n"
                + "insert into formType ([code], [desc]) values (3, 'DP-3')");

            db.DataTables.Add(formType);
            db.DataTables.Add(emptyTable);
            db.Dir = db.Name;

            if (Directory.Exists(db.Dir))
                Directory.Delete(db.Dir, true);

            db.ScriptToDir();
            Assert.IsTrue(Directory.Exists(db.Name));
            Assert.IsTrue(Directory.Exists(db.Name + "\\data"));
            Assert.IsTrue(Directory.Exists(db.Name + "\\tables"));
            Assert.IsTrue(Directory.Exists(db.Name + "\\foreign_keys"));

            foreach (var t in db.DataTables) {
                if (t.Name == "EmptyTable") {
                    Assert.IsFalse(File.Exists(db.Name + "\\data\\" + t.Name + ".tsv"));
                } else {
                    Assert.IsTrue(File.Exists(db.Name + "\\data\\" + t.Name + ".tsv"));
                }
            }
            foreach (var t in db.Tables) {
                var tblFile = db.Name + "\\tables\\" + t.Name + ".sql";
                Assert.IsTrue(File.Exists(tblFile));

                // Test that the constraints are ordered in the file
                string script = File.ReadAllText(tblFile);
                int cindex = -1;

                foreach (var ckobject in t.Constraints.OrderBy(x => x.Name))
                {
                    var thisindex = script.IndexOf(ckobject.ScriptCreate());
                    Assert.Greater(thisindex, cindex, "Constraints are not ordered.");

                    cindex = thisindex;
                }

            }
            foreach (var t in db.TableTypes) {
                Assert.IsTrue(File.Exists(db.Name + "\\table_types\\TYPE_" + t.Name + ".sql"));
            }
            foreach (var expected in db.ForeignKeys.Select(fk => db.Name + "\\foreign_keys\\" + fk.Table.Name + ".sql")) {
                Assert.IsTrue(File.Exists(expected), "File does not exist" + expected);
            }

            // Test that the foreign keys are ordered in the file
            foreach (var t in db.Tables)
            {
                var fksFile = db.Name + "\\foreign_keys\\" + t.Name + ".sql";

                if (File.Exists(fksFile))
                {
                    string script = File.ReadAllText(fksFile);
                    int fkindex = -1;

                    foreach (var fkobject in db.ForeignKeys.Where(x => x.Table == t).OrderBy(x => x.Name))
                    {
                        var thisindex = script.IndexOf(fkobject.ScriptCreate());
                        Assert.Greater(thisindex, fkindex, "Foreign keys are not ordered.");

                        fkindex = thisindex;
                    }
                }

            }

            var copy = new Database("ScriptToDirTestCopy");
            copy.Dir = db.Dir;
            copy.Connection = ConfigHelper.TestDB.Replace("database=TESTDB", "database=" + copy.Name);
            copy.CreateFromDir(true);
            copy.Load();
            TestCompare(db, copy);
        }
コード例 #14
0
ファイル: DatabaseTester.cs プロジェクト: sethreno/schemazen
        public void TestScript()
        {
            var db = new Database("TEST_TEMP");
            var t1 = new Table("dbo", "t1");
            t1.Columns.Add(new Column("col1", "int", false, null) {Position = 1});
            t1.Columns.Add(new Column("col2", "int", false, null) {Position = 2});
            t1.AddConstraint(new Constraint("pk_t1", "PRIMARY KEY", "col1,col2"));
            t1.FindConstraint("pk_t1").Clustered = true;

            var t2 = new Table("dbo", "t2");
            t2.Columns.Add(new Column("col1", "int", false, null) {Position = 1});
            t2.Columns.Add(new Column("col2", "int", false, null) {Position = 2});
            t2.Columns.Add(new Column("col3", "int", false, null) {Position = 3});
            t2.AddConstraint(new Constraint("pk_t2", "PRIMARY KEY", "col1"));
            t2.FindConstraint("pk_t2").Clustered = true;
            t2.AddConstraint(new Constraint("IX_col3", "UNIQUE", "col3"));

            db.ForeignKeys.Add(new ForeignKey(t2, "fk_t2_t1", "col2,col3", t1, "col1,col2"));

            db.Tables.Add(t1);
            db.Tables.Add(t2);

            TestHelper.DropDb("TEST_TEMP");
            SqlConnection.ClearAllPools();
            TestHelper.ExecBatchSql(db.ScriptCreate(), "master");

            var db2 = new Database();
            db2.Connection = TestHelper.GetConnString("TEST_TEMP");
            db2.Load();

            TestHelper.DropDb("TEST_TEMP");

            foreach (var t in db.Tables) {
                Assert.IsNotNull(db2.FindTable(t.Name, t.Owner));
                Assert.IsFalse(db2.FindTable(t.Name, t.Owner).Compare(t).IsDiff);
            }
        }