重复:从XML生成SQL模式
在我正在开发的项目中,我需要支持强类型数据集,用于将数据存储为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
希望这有助于其他人.