重複:Generating SQL Schema from XML生成SQL Server數據庫從XSD
在一個項目中我的工作,我有必要爲支持一個強類型數據集數據存儲爲XML,或存儲在sql server中的數據。現在我已經創建了XSD模式,並且希望能夠使用XSD中定義的表和關係創建一個sql server數據庫。
這可能嗎?如果是的話,解決這個問題的最好方法是什麼?
澄清: 我正在尋找一種方法通過代碼在C#和SQL Server運行時做以上。這可以做到嗎?
重複:Generating SQL Schema from XML生成SQL Server數據庫從XSD
在一個項目中我的工作,我有必要爲支持一個強類型數據集數據存儲爲XML,或存儲在sql server中的數據。現在我已經創建了XSD模式,並且希望能夠使用XSD中定義的表和關係創建一個sql server數據庫。
這可能嗎?如果是的話,解決這個問題的最好方法是什麼?
澄清: 我正在尋找一種方法通過代碼在C#和SQL Server運行時做以上。這可以做到嗎?
我管理的基於SQL Server管理對象來與下面的類:
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Text;
using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Smo;
using Rule=System.Data.Rule;
namespace XSD2SQL
{
public class XSD2SQL
{
private readonly Server _server;
private readonly SqlConnection _connection;
private Database _db;
private DataSet _source;
private string _databaseName;
public XSD2SQL(string connectionString, DataSet source)
{
_connection = new SqlConnection(connectionString);
_server = new Server(new ServerConnection(_connection));
_source = source;
}
public void CreateDatabase(string databaseName)
{
_databaseName = databaseName;
_db = _server.Databases[databaseName];
if (_db != null) _db.Drop();
_db = new Database(_server, _databaseName);
_db.Create();
}
public void PopulateDatabase()
{
CreateTables(_source.Tables);
CreateRelationships();
}
private void CreateRelationships()
{
foreach (DataTable table in _source.Tables)
{
foreach (DataRelation rel in table.ChildRelations)
CreateRelation(rel);
}
}
private void CreateRelation(DataRelation relation)
{
Table primaryTable = _db.Tables[relation.ParentTable.TableName];
Table childTable = _db.Tables[relation.ChildTable.TableName];
ForeignKey fkey = new ForeignKey(childTable, relation.RelationName);
fkey.ReferencedTable = primaryTable.Name;
fkey.DeleteAction = SQLActionTypeToSMO(relation.ChildKeyConstraint.DeleteRule);
fkey.UpdateAction = SQLActionTypeToSMO(relation.ChildKeyConstraint.UpdateRule);
for (int i = 0; i < relation.ChildColumns.Length; i++)
{
DataColumn col = relation.ChildColumns[i];
ForeignKeyColumn fkc = new ForeignKeyColumn(fkey, col.ColumnName, relation.ParentColumns[i].ColumnName);
fkey.Columns.Add(fkc);
}
fkey.Create();
}
private void CreateTables(DataTableCollection tables)
{
foreach (DataTable table in tables)
{
DropExistingTable(table.TableName);
Table newTable = new Table(_db, table.TableName);
PopulateTable(ref newTable, table);
SetPrimaryKeys(ref newTable, table);
newTable.Create();
}
}
private void PopulateTable(ref Table outputTable, DataTable inputTable)
{
foreach (DataColumn column in inputTable.Columns)
{
CreateColumns(ref outputTable, column, inputTable);
}
}
private void CreateColumns(ref Table outputTable, DataColumn inputColumn, DataTable inputTable)
{
Column newColumn = new Column(outputTable, inputColumn.ColumnName);
newColumn.DataType = CLRTypeToSQLType(inputColumn.DataType);
newColumn.Identity = inputColumn.AutoIncrement;
newColumn.IdentityIncrement = inputColumn.AutoIncrementStep;
newColumn.IdentitySeed = inputColumn.AutoIncrementSeed;
newColumn.Nullable = inputColumn.AllowDBNull;
newColumn.UserData = inputColumn.DefaultValue;
outputTable.Columns.Add(newColumn);
}
private void SetPrimaryKeys(ref Table outputTable, DataTable inputTable)
{
Index newIndex = new Index(outputTable, "PK_" + outputTable.Name);
newIndex.IndexKeyType = IndexKeyType.DriPrimaryKey;
newIndex.IsClustered = false;
foreach (DataColumn keyColumn in inputTable.PrimaryKey)
{
newIndex.IndexedColumns.Add(new IndexedColumn(newIndex, keyColumn.ColumnName, true));
}
if (newIndex.IndexedColumns.Count > 0)
outputTable.Indexes.Add(newIndex);
}
private DataType CLRTypeToSQLType(Type type)
{
switch (type.Name)
{
case "String":
return DataType.NVarCharMax;
case "Int32":
return DataType.Int;
case "Boolean":
return DataType.Bit;
case "DateTime":
return DataType.DateTime;
case "Byte[]":
return DataType.VarBinaryMax;
}
return DataType.NVarCharMax;
}
private ForeignKeyAction SQLActionTypeToSMO(Rule rule)
{
string ruleStr = rule.ToString();
return (ForeignKeyAction)Enum.Parse(typeof (ForeignKeyAction), ruleStr);
}
private void DropExistingTable(string tableName)
{
Table table = _db.Tables[tableName];
if (table != null) table.Drop();
}
}
}
它並沒有經過嚴格的測試着呢,需要有更多的SQL CLR映射出類型,但它確實創建了一個新的數據庫,所有表,列,主鍵和外鍵。
對於此代碼工作,一些組件需要被引用:
Microsoft.SqlServer.ConnectionInfo
Microsoft.SqlServer.Management.Sdk.Sfc
Microsoft.SqlServer.Smo
Microsoft.SqlServer.SqlEnum
希望這可以幫助其他人了。
我會寫一些XSLT將XSD轉換爲SQL創建語句。
如果您正在使用SQL2005,則可以使用強類型XML列創建表,以便每個值都針對XML模式集合(即XSD)進行驗證。但是我不能告訴你關於性能,可擴展性等什麼
如果您嘗試翻譯的XSD到一組關係表,你會發現,有XSD元素和SQL表之間不存在唯一的對應關係:
一個XSD子元素可以被實現爲細節表,作爲表示元素的一組列(如果只允許一個孩子),或者作爲強制/可選1:1/1:n關係來實現。
XSD子元素的集合可以是一個主 - 關係關係,或一個n:m關係以及屬性存儲在一個單獨的表中。
IIRC XSD中沒有主要和唯一約束的定義,這在自動化模式生成中帶來了另一個問題。
這並不意味着沒有人會爲開發此類任務的工具而煩惱。但這當然意味着這項任務不能完全自動化。
Duplicate:http://stackoverflow.com/questions/263836/generating-sql-schema-from-xml – 2009-01-21 22:39:28
不是重複的,因爲其他問題指的是oracle和java;這一個涉及SQL Server – devio 2009-01-21 22:56:10