酷数据库工具





4.00/5 (2投票s)
酷数据库工具。
在过去的两个月(2008年1月/2月),我在Codeproject赢得了C#月度文章奖,因此,我收到了很多免费软件。通常我从来不看这些软件。原因很简单。我写文章是为了与他人分享,所以这些免费软件对我来说没什么用。因为当我发表一篇新文章时,文章的读者不会安装与我相同的软件,因此无法在Visual Studio中运行我的代码。
因此,由于这个原因,我很少去看那些免费软件。
然而,在工作中,我经常与数据库打交道,以前都是SQL Server 2005。但现在是Oracle 10g。尽管我仍然更喜欢SQL Server。
所以因为我喜欢SQL Server,我一直在寻找可以帮助我日常工作的酷炫的东西。
在Codeproject这两个月的奖品中,有一个产品实际上值得一看。因为我过去做过很多数据库相关的事情,所以我很欣赏任何能节省我时间的工具。我觉得这就是其中一款产品。
该产品是一个数据库重新同步组件。请注意,它不是一个应用程序,而是一个组件,这意味着您可以将其直接嵌入到您的应用程序中,并通过直接调用该组件上的UpdateDatabase()
来使用它。
该组件名为“Database Restyle”,由一家名为Perpetuumsoft的公司开发,它可以直接集成到.NET项目中。
我认为展示组件功能的最好方法是看看它能做什么。我使用的是安装了标准Northwind
数据库的SQL Server 2005。
现在跳转到Visual Studio(我使用的是VS2008),我们可以看到有一个实际的组件可以拖到Winforms/Console/Web应用程序中。
现在在代码中,我可以简单地使用组件的update
方法,我的数据库将与当前模式上已更改的任何内容重新同步。这就是该应用程序使用的模型。
也许这里需要一个例子。我使用的是Database Restyle组件安装示例中附带的示例。
1: /*****************************************************************************
2:
3: This source file is a part of Database Restyle
4:
5: Copyright (c) 2008 Perpetuum Software LLC. All rights reserved.
6: THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
7: OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
8: LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
9: FITNESS FOR A PARTICULAR PURPOSE.
10:
11: Copyright (c) 2008 Perpetuum Software LLC. All rights reserved.
12:
13: *****************************************************************************/
14: using System;
15: using System.Collections.Generic;
16: using System.ComponentModel;
17: using System.Data;
18: using System.Data.SqlClient;
19: using System.Data.Linq.Mapping;
20: using System.Drawing;
21: using System.Linq;
22: using System.Text;
23: using System.Windows.Forms;
24: using PerpetuumSoft.DataModel.MsSql.Synchronizers;
25: using PerpetuumSoft.DataModel.MsSql;
26: using PerpetuumSoft.DataModel.LinqToSql;
27:
28: namespace LinqToSql
29: {
30: public partial class MainForm : Form
31: {
32: public MainForm()
33: {
34: InitializeComponent();
35: dbBuilder.CreateFunctions = true;
36: dbBuilder.FunctionRequire += new
37: EventHandler<PerpetuumSoft.DataModel.FunctionRequareEventArgs>
38: dbBuilder_FunctionRequire);
39: }
40:
41: private StringBuilder log;
42:
43: private LinqDatabaseBuilder dbBuilder = new LinqDatabaseBuilder();
44:
45: private void dbBuilder_FunctionRequire(object sender,
46: PerpetuumSoft.DataModel.FunctionRequareEventArgs e)
47: {
48: if (e.SchemaName == "dbo" && e.FunctionName == "ProductsUnderThisUnitPrice")
49: {
50: string text =
51: @"CREATE FUNCTION [dbo].[ProductsUnderThisUnitPrice]()
52: RETURNS int
53: AS
54: BEGIN
55: DECLARE @retval int
56: SELECT @retval = COUNT(*) FROM Territory
57: RETURN @retval
58: END;";
59: ScalarFunction function = new
60: PerpetuumSoft.DataModel.MsSql.ScalarFunction(e.FunctionName,
text);
61: function.ReturnValueType = new DataType.Int();
62: e.Function = function;
63: }
64: else
65: {
66: throw new Exception(String.Format("Unknown function: [{0}].[{1}].",
67: e.SchemaName, e.FunctionName));
68: }
69: }
70:
71: private void exitButton_Click(object sender, EventArgs e)
72: {
73: this.Close();
74: }
75:
76: private void syncButton_Click(object sender, EventArgs e)
77: {
78: try
79: {
80: log = new StringBuilder();
81:
82: MetaModel model = new AttributeMappingSource().
83: GetModel(typeof(DataClassesDataContext));
84: Database sourceDB = dbBuilder.CreateDatabase(model);
85: databaseSync.UpdateDatabase(sourceDB, GetConnectionString());
86:
87: logTextBox.Text = log.ToString();
88: }
89: catch (Exception ex)
90: {
91: logTextBox.Text = log.ToString();
92: logTextBox.Text += ex.ToString();
93: }
94: }
95:
96: private string GetConnectionString()
97: {
98: SqlConnectionStringBuilder connectionString =
99: new SqlConnectionStringBuilder();
100: connectionString.IntegratedSecurity = true;
101: connectionString.InitialCatalog = databaseName.Text;
102: connectionString.DataSource = serverName.Text;
103: return connectionString.ConnectionString;
104: }
105:
106: private void databaseSync_ScriptExecuting(object sender,
107: PerpetuumSoft.DataModel.ScriptExecuteEventArgs e)
108: {
109: log.AppendLine(e.Text);
110: }
111:
112: private void databaseSync_DatabaseUpdating(object sender,
113: PerpetuumSoft.DataModel.DatabaseUpdatingEventArgs e)
114: {
115: log.Append("Begin synchronize: [");
116: log.Append(DateTime.Now.ToLongTimeString());
117: log.AppendLine("]");
118: }
119:
120: private void databaseSync_DatabaseUpdated(object sender, EventArgs e)
121: {
122: log.Append("End synchronize: [");
123: log.Append(DateTime.Now.ToLongTimeString());
124: log.Append("]");
125: }
126:
127: private void clearDbButton_Click(object sender, EventArgs e)
128: {
129: try
130: {
131: log = new StringBuilder();
132:
133: Database sourceDB = Database.CreateDatabaseWithSystemObjects();
134: databaseSync.UpdateDatabase(sourceDB, GetConnectionString());
135:
136: logTextBox.Text = log.ToString();
137: }
138: catch (Exception ex)
139: {
140: logTextBox.Text = log.ToString();
141: logTextBox.Text += ex.ToString();
142: }
143: }
144:
145: private void viewScriptsButton_Click(object sender, EventArgs e)
146: {
147: try
148: {
149: log = new StringBuilder();
150:
151: MetaModel model = new AttributeMappingSource().
152: GetModel(typeof(DataClassesDataContext));
153: Database sourceDB = dbBuilder.CreateDatabase(model);
154: DatabaseSynchronizer dbSynchronizer =
155: databaseSync.Compare(sourceDB,
156: databaseSync.ReverseDatabase(GetConnectionString()));
157: foreach (Script script in dbSynchronizer.Scripts)
158: {
159: log.AppendLine(script.GetText());
160: }
161: logTextBox.Text = log.ToString();
162: }
163: catch (Exception ex)
164: {
165: logTextBox.Text = log.ToString();
166: logTextBox.Text += ex.ToString();
167: }
168: }
169:
170: }
171: }
上面最重要的几行是这些
1: MetaModel model = new AttributeMappingSource().
2: GetModel(typeof(DataClassesDataContext));
3: Database sourceDB = dbBuilder.CreateDatabase(model);
4: databaseSync.UpdateDatabase(sourceDB, GetConnectionString());
此示例使用LINQ to SQL文件作为数据库模式,该模式是运行时形成应用程序模型的模式。因此,这将是执行重新同步时与底层数据库进行比较的来源。可以看出,该模型(LINQ to SQL)存在3个表。这些表已经存在于底层的Northwind
数据库中。
Here they are
但在与我之前展示的表单相关的代码中,创建了一个名为“ProductsUnderThisUnitPrice
”的新Function
,该Function
不存在于底层的Northwind
数据库中。
因此,运行应用程序会显示Database Restyle组件创建的这个新函数。
这很好,但是它实际上在底层数据库中创建了这个函数吗?
答案是可以。
因此,使用演示代码,我决定做一些激进的事情,清除数据库,然后进行重新同步。这也很有效。您可以在下面看到生成了一堆SQL来DROP
表/约束等。
回到SQL,我们可以看到这些表不再位于Northwind
数据库中。
然后我点击了“同步”按钮,回到SQL Server,一切又恢复了。这是该组件生成的用于重新创建架构的脚本。
1: Begin synchronize: [08:49:24]
2:
3: CREATE TABLE [dbo].[Categories]([CategoryID] INT NOT NULL IDENTITY(1,1),
4: [CategoryName] NVARCHAR(15) NOT NULL ,[Description] NTEXT NULL ,[Picture] IMAGE NULL )
5:
6: ALTER TABLE [dbo].[Categories] ADD CONSTRAINT [PK_Categories] PRIMARY KEY
7: NONCLUSTERED ([CategoryID] ASC) WITH(PAD_INDEX = OFF,IGNORE_DUP_KEY = OFF,
8: STATISTICS_NORECOMPUTE = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON)
9:
10: CREATE TABLE [dbo].[Products]([ProductID] INT NOT NULL IDENTITY(1,1),
11: [ProductName] NVARCHAR(40) NOT NULL ,[SupplierID] INT NULL ,[CategoryID] INT NULL ,
12: [QuantityPerUnit] NVARCHAR(20) NULL ,[UnitPrice] MONEY NULL ,[UnitsInStock] SMALLINT NULL ,
13: [UnitsOnOrder] SMALLINT NULL ,[ReorderLevel] SMALLINT NULL ,[Discontinued] BIT NOT NULL )
14:
15: ALTER TABLE [dbo].[Products] ADD CONSTRAINT [PK_Products]
16: PRIMARY KEY NONCLUSTERED ([ProductID] ASC)
17: WITH(PAD_INDEX = OFF,IGNORE_DUP_KEY = OFF,STATISTICS_NORECOMPUTE = OFF,
18: ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON)
19:
20: CREATE TABLE [dbo].[Suppliers]([SupplierID] INT NOT NULL IDENTITY(1,1),
21: [CompanyName] NVARCHAR(40) NOT NULL ,[ContactName] NVARCHAR(30) NULL ,
22: [ContactTitle] NVARCHAR(30) NULL ,[Address] NVARCHAR(60) NULL ,[City] NVARCHAR(15) NULL ,
23: [Region] NVARCHAR(15) NULL ,[PostalCode] NVARCHAR(10) NULL ,[Country] NVARCHAR(15) NULL ,
24: [Phone] NVARCHAR(24) NULL ,[Fax] NVARCHAR(24) NULL ,[HomePage] NTEXT NULL )
25:
26: ALTER TABLE [dbo].[Suppliers] ADD CONSTRAINT [PK_Suppliers]
27: PRIMARY KEY NONCLUSTERED ([SupplierID] ASC) WITH(PAD_INDEX = OFF,IGNORE_DUP_KEY = OFF,
28: STATISTICS_NORECOMPUTE = OFF,ALLOW_ROW_LOCKS = ON,ALLOW_PAGE_LOCKS = ON)
29:
30: ALTER TABLE [dbo].[Products] WITH CHECK ADD CONSTRAINT [Category_Product]
31: FOREIGN KEY (CategoryID) REFERENCES [dbo].[Categories] (CategoryID)
32: ON UPDATE NO ACTION ON DELETE NO ACTION
33:
34: ALTER TABLE [dbo].[Products] WITH CHECK ADD CONSTRAINT [Supplier_Product]
35: FOREIGN KEY (SupplierID) REFERENCES [dbo].[Suppliers] (SupplierID)
36: ON UPDATE NO ACTION ON DELETE NO ACTION
37:
38: CREATE FUNCTION [dbo].[ProductsUnderThisUnitPrice]()
39: RETURNS int
40: AS
41: BEGIN
42: DECLARE @retval int
43: SELECT @retval = COUNT(*) FROM Territory
44: RETURN @retval
45: END;
46: End synchronize: [08:49:24]
这是同步后的屏幕截图。
很酷,不是吗?
Perpetuumsoft还声称支持除使用LINQ to SQL之外的其他模式。
总而言之,我认为这是一个非常好的易于使用的产品。我认为这是一个非常有用(这就是我费心写博客的原因)的产品,并且每当我回到使用SQL Server时,我都将推动使用它。
如果您想下载并试用它,这是Perpetuumsoft的网站。