如何将数据导入到 SQL Server Compact Edition 数据库中(三)
点击次数:17 次 发布日期:2008-11-26 22:30:22 作者:源代码网
|
源代码网推荐 系列文章导航: 源代码网推荐 如何将数据导入到 SQL Server Compact Edition 数据库中(一) 源代码网推荐 如何将数据导入到 SQL Server Compact Edition 数据库中(二) 源代码网推荐 源代码网推荐 摘要:时隔近半年了,不知道大家是否还记得,我在本系列的第一篇文章的总结中提到,创建 SQL Server CE 数据库表结构的 SQL 语句是可以自动生成的。那么本系列的第三篇文章就向大家介绍一种比较简单的方法。 源代码网推荐 源代码网推荐 ADO.NET 中的 IDataReader.GetSchemaTable 方法可以返回一个 DataTable,它描述了 IDataReader 查询结果中各列的元数据。列的元数据包含了列的名称、数据类型、大小、是否为主键字段、是否为自动增长字段……等等。有了这些元数据,我们就可以通过编写几段 C#/VB.NET 代码,实现创建 SQL Server CE 数据库表结构的 SQL 语句的自动生成。以下方法是生成创建表 SQL 语句的主要代码: 源代码网推荐 源代码网推荐 /// <summary> 源代码网推荐 /// 生成创建数据库表结构的 SQL 语句。 源代码网推荐 /// </summary> 源代码网推荐 private static string GenerateTableSchemaSql(IDbConnection connection, string queryString) 源代码网推荐 { 源代码网推荐 StringBuilder tableSql = new StringBuilder(); 源代码网推荐 源代码网推荐 IDbCommand command = connection.CreateCommand(); 源代码网推荐 command.CommandText = queryString; 源代码网推荐 源代码网推荐 try 源代码网推荐 { 源代码网推荐 /* 获取查询结果各列的元数据 */ 源代码网推荐 DataTable schemaTable = null; 源代码网推荐 using (IDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo)) 源代码网推荐 { 源代码网推荐 schemaTable = reader.GetSchemaTable(); 源代码网推荐 } 源代码网推荐 源代码网推荐 /* 生成创建表定义语句 */ 源代码网推荐 string tableName = schemaTable.Rows[0]["BaseTableName"].ToString(); 源代码网推荐 tableSql.Append("CREATE TABLE [").Append(tableName).AppendLine("] ("); 源代码网推荐 源代码网推荐 /* 生成各列的定义语句 */ 源代码网推荐 string columnName; 源代码网推荐 string allowDBNull; 源代码网推荐 DataRow row; 源代码网推荐 bool hasKey = false; 源代码网推荐 StringBuilder sbPKFields = new StringBuilder(); 源代码网推荐 for (int i = 0; i < schemaTable.Rows.Count; i++) 源代码网推荐 { 源代码网推荐 if (i != 0) tableSql.AppendLine(","); 源代码网推荐 源代码网推荐 row = schemaTable.Rows[i]; 源代码网推荐 columnName = (string)row["ColumnName"]; 源代码网推荐 allowDBNull = ((bool)row["AllowDBNull"] == true ? "NULL" : "NOT NULL"); 源代码网推荐 源代码网推荐 if ((bool)row["IsKey"]) 源代码网推荐 { 源代码网推荐 sbPKFields.AppendFormat("[{0}],", columnName); 源代码网推荐 hasKey = true; 源代码网推荐 } 源代码网推荐 tableSql.AppendFormat(" [{0}] {1} {2}", columnName, GetSqlCeDataType(row), allowDBNull); 源代码网推荐 } 源代码网推荐 源代码网推荐 /* 生成主键约束语句 */ 源代码网推荐 if (hasKey) 源代码网推荐 { 源代码网推荐 string pkFields = sbPKFields.ToString().TrimEnd(","); 源代码网推荐 tableSql.AppendLine(","); 源代码网推荐 tableSql.Append(" CONSTRAINT PK_").Append(tableName).Append(" PRIMARY KEY(").Append(pkFields).AppendLine(")"); 源代码网推荐 } 源代码网推荐 tableSql.AppendLine(");"); 源代码网推荐 } 源代码网推荐 catch (Exception ex) 源代码网推荐 { 源代码网推荐 Debug.WriteLine(ex); 源代码网推荐 } 源代码网推荐 源代码网推荐 return tableSql.ToString(); 源代码网推荐 } 源代码网推荐 同样的,该方法也使用了 ADO.NET 的接口类,不依赖于具体的数据库类型。该方法的核心就是通过 IDataReader.GetSchemaTable 方法获取查询结果各列元数据,相关代码如下: 源代码网推荐 源代码网推荐 IDbCommand command = connection.CreateCommand(); 源代码网推荐 command.CommandText = queryString; 源代码网推荐 DataTable schemaTable = null; 源代码网推荐 using (IDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo)) 源代码网推荐 { 源代码网推荐 schemaTable = reader.GetSchemaTable(); 源代码网推荐 } 源代码网推荐 首先,IDbCommand 的 CommandText 属性一般是针对一个表的 SELECT 查询语句,如:SELECT * FROM Customers。其次,IDbCommand.ExecuteReader 方法必须传入 CommandBehavior.KeyInfo 参数,这样才能获取到列的主键元数据。最后,通过 IDataReader.GetSchemaTable 方法返回一个包含查询结果所有列的元数据的 DataTable。关于 IDataReader.GetSchemaTable 方法的详细使用说明,请阅读《HOW TO:使用 DataReader GetSchemaTable 方法和 Visual C# .NET 检索列架构》。 源代码网推荐 源代码网推荐 IDataReader.GetSchemaTable 返回的 SchemaTable 对列数据类型的描述是用相应的 .NET 数据类型,如 SQL Server CE 的 int 类型对应的是 .NET 的 System.Int32 类型。另外需要注意的是,由于 Windows Mobile 只支持 Unicode 编码,因此 SQL Server CE 只支持 NChar, NVarChar 和 NText 等 Unicode 字符数据类型,而不支持 Char, VarChar 和 Text 等非 Unicode 字符数据类型。所以,我们需要编写一个方法,它根据列的 .NET 数据类型找到对应的 SQL Server CE 数据类型。这个方法的代码如下所示: 源代码网推荐 源代码网推荐 /// <summary> 源代码网推荐 /// 从 .NET 数据类型获取对应的 SQL Server CE 类型名称。 源代码网推荐 /// </summary> 源代码网推荐 private static string GetSqlCeNativeType(Type systemType) 源代码网推荐 { 源代码网推荐 string typeName = systemType.ToString(); 源代码网推荐 switch (typeName) 源代码网推荐 { 源代码网推荐 case "System.Boolean": 源代码网推荐 return "bit"; 源代码网推荐 case "System.Byte": 源代码网推荐 return "tinyint"; 源代码网推荐 case "System.Byte[]": 源代码网推荐 return "image"; 源代码网推荐 case "System.DateTime": 源代码网推荐 return "datetime"; 源代码网推荐 case "System.Decimal": 源代码网推荐 return "numeric"; 源代码网推荐 case "System.Double": 源代码网推荐 return "float"; 源代码网推荐 case "System.Guid": 源代码网推荐 return "uniqueidentifier"; 源代码网推荐 case "System.Int16": 源代码网推荐 return "smallint"; 源代码网推荐 case "System.Int32": 源代码网推荐 return "integer"; 源代码网推荐 case "System.Int64": 源代码网推荐 return "bigint"; 源代码网推荐 case "System.Single": 源代码网推荐 return "real"; 源代码网推荐 case "System.String": 源代码网推荐 return "nvarchar"; 源代码网推荐 default: 源代码网推荐 throw new ApplicationException(string.Format("找不到 {0} 类型对应的 SQL Server CE 数据类型。", typeName)); 源代码网推荐 } 源代码网推荐 } 源代码网推荐 当然,仅仅知道列的数据类型还不够,我们需要为某些列的数据类型加上长度、精度或小数位数等列大小信息。可以通过下面的方法实现: 源代码网推荐 源代码网推荐 /// <summary> 源代码网推荐 /// 从 ColumnSchemaRow 获取 SQL Server CE 数据类型。 源代码网推荐 /// </summary> 源代码网推荐 private static string GetSqlCeDataType(DataRow columnSchemaRow) 源代码网推荐 { 源代码网推荐 Type type = columnSchemaRow["DataType"] as Type; 源代码网推荐 string dataType = GetSqlCeNativeType(type); 源代码网推荐 switch (dataType) 源代码网推荐 { 源代码网推荐 case "numeric": 源代码网推荐 Int16 precision = (Int16)columnSchemaRow["NumericPrecision"]; 源代码网推荐 Int16 scale = (Int16)columnSchemaRow["NumericScale"]; 源代码网推荐 if (precision != 0 && scale != 0) 源代码网推荐 { 源代码网推荐 dataType = string.Format("{0}({1},{2})", dataType, precision, scale); 源代码网推荐 } 源代码网推荐 break; 源代码网推荐 case "nvarchar": 源代码网推荐 int columnSize = (int)columnSchemaRow["ColumnSize"]; 源代码网推荐 if (columnSize > 4000) 源代码网推荐 { 源代码网推荐 dataType = "ntext"; 源代码网推荐 } 源代码网推荐 else 源代码网推荐 { 源代码网推荐 dataType = string.Format("{0}({1})", dataType, columnSize); 源代码网推荐 } 源代码网推荐 break; 源代码网推荐 } 源代码网推荐 return dataType; 源代码网推荐 } 源代码网推荐 关于 SQL Server 2005 Compact Edition 数据类型的描述,详细请参考联机丛书。使用上面的几段代码,对 SQL Server 2000 自带的 Northwind 数据库的 Customers 表生成创建数据库表的 SQL 语句,生成结果如下: 源代码网推荐 源代码网推荐 CREATE TABLE [Customers] ( 源代码网推荐 [CustomerID] nvarchar(5) NOT NULL, 源代码网推荐 [CompanyName] nvarchar(40) NOT NULL, 源代码网推荐 [ContactName] nvarchar(30) NULL, 源代码网推荐 [ContactTitle] nvarchar(30) NULL, 源代码网推荐 [Address] nvarchar(60) NULL, 源代码网推荐 [City] nvarchar(15) NULL, 源代码网推荐 [Region] nvarchar(15) NULL, 源代码网推荐 [PostalCode] nvarchar(10) NULL, 源代码网推荐 [Country] nvarchar(15) NULL, 源代码网推荐 [Phone] nvarchar(24) NULL, 源代码网推荐 [Fax] nvarchar(24) NULL, 源代码网推荐 CONSTRAINT PK_Customers PRIMARY KEY([CustomerID]) 源代码网推荐 ); 源代码网推荐 对于 SQL Server 2000,我们可以从信息架构视图查询 INFORMATION_SCHEMA.TABLES 出数据库有哪些表,并一次性对所有表进行生成。以下是 INFORMATION_SCHEMA.TABLES 视图各列的说明: 列名 数据类型 说明 源代码网推荐 TABLE_CATALOG nvarchar(128) 表限定符。 源代码网推荐 TABLE_SCHEMA nvarchar(128) 包含该表的架构的名称。 源代码网推荐 TABLE_NAME sysname 表名。 源代码网推荐 TABLE_TYPE varchar(10) 表的类型。可以是 VIEW 或 BASE TABLE。 源代码网推荐 源代码网推荐 源代码网推荐 我们可以通过以下方法获得 Northwind 数据库所有用户表名的数组: 源代码网推荐 源代码网推荐 /// <summary> 源代码网推荐 /// 从一个打开的 SQL Server 数据库连接获取数据库的表名数组。 源代码网推荐 /// </summary> 源代码网推荐 private static string[] GetTableNames(IDbConnection connection) 源代码网推荐 { 源代码网推荐 IDbCommand command = connection.CreateCommand(); 源代码网推荐 源代码网推荐 // 从 SQL Server 信息架构视图获取 Northwind 数据库所有表的名称 源代码网推荐 command.CommandText = @"SELECT * FROM INFORMATION_SCHEMA.TABLES 源代码网推荐 WHERE TABLE_TYPE="BASE TABLE" AND TABLE_CATALOG="Northwind""; 源代码网推荐 源代码网推荐 List<string> tableNames = new List<string>(); 源代码网推荐 using (IDataReader reader = command.ExecuteReader()) 源代码网推荐 { 源代码网推荐 while (reader.Read()) 源代码网推荐 { 源代码网推荐 tableNames.Add(reader["TABLE_NAME"].ToString()); 源代码网推荐 } 源代码网推荐 } 源代码网推荐 return tableNames.ToArray(); 源代码网推荐 } 源代码网推荐 有了 GetTableNames 方法,我们就可以一次性对 Northwind 数据库的所有用户表生成相应的创建 SQL Server CE 数据库表结构的 SQL 语句。 源代码网推荐 源代码网推荐 static void Main(string[] args) 源代码网推荐 { 源代码网推荐 string connectionString = "Data Source=(local);Initial Catalog=Northwind;Integrated Security=True"; 源代码网推荐 IDbConnection connection = new SqlConnection(connectionString); 源代码网推荐 connection.Open(); 源代码网推荐 源代码网推荐 string[] tableNames = GetTableNames(connection); 源代码网推荐 源代码网推荐 string queryString, createTableSql; 源代码网推荐 foreach (string tableName in tableNames) 源代码网推荐 { 源代码网推荐 queryString = string.Format("select * from [{0}]", tableName); 源代码网推荐 createTableSql = GenerateTableSchemaSql(connection, queryString); 源代码网推荐 源代码网推荐 Console.WriteLine(createTableSql); 源代码网推荐 Debug.WriteLine(createTableSql); 源代码网推荐 } 源代码网推荐 源代码网推荐 connection.Close(); 源代码网推荐 Console.Read(); 源代码网推荐 } 源代码网推荐 示例程序运行效果如下图所示: 源代码网推荐
源代码网推荐 完整代码: 源代码网推荐 完整代码 源代码网推荐 using System; 源代码网推荐 using System.Collections.Generic; 源代码网推荐 using System.Text; 源代码网推荐 using System.Data.SqlClient; 源代码网推荐 using System.Data; 源代码网推荐 using System.Diagnostics; 源代码网推荐 源代码网推荐 namespace GenTableSchema 源代码网推荐 { 源代码网推荐 class Program 源代码网推荐 { 源代码网推荐 static void Main(string[] args) 源代码网推荐 { 源代码网推荐 string connectionString = "Data Source=(local);Initial Catalog=Northwind;Integrated Security=True"; 源代码网推荐 IDbConnection connection = new SqlConnection(connectionString); 源代码网推荐 connection.Open(); 源代码网推荐 源代码网推荐 string[] tableNames = GetTableNames(connection); 源代码网推荐 源代码网推荐 string queryString, createTableSql; 源代码网推荐 foreach (string tableName in tableNames) 源代码网推荐 { 源代码网推荐 queryString = string.Format("select * from [{0}]", tableName); 源代码网推荐 createTableSql = GenerateTableSchemaSql(connection, queryString); 源代码网推荐 源代码网推荐 Console.WriteLine(createTableSql); 源代码网推荐 Debug.WriteLine(createTableSql); 源代码网推荐 } 源代码网推荐 源代码网推荐 connection.Close(); 源代码网推荐 Console.Read(); 源代码网推荐 } 源代码网推荐 源代码网推荐 /// <summary> 源代码网推荐 /// 从一个打开的 SQL Server 数据库连接获取数据库的表名数组。 源代码网推荐 /// </summary> 源代码网推荐 private static string[] GetTableNames(IDbConnection connection) 源代码网推荐 { 源代码网推荐 IDbCommand command = connection.CreateCommand(); 源代码网推荐 源代码网推荐 // 从 SQL Server 信息架构视图获取 Northwind 数据库所有表的名称 源代码网推荐 command.CommandText = @"SELECT * FROM INFORMATION_SCHEMA.TABLES 源代码网推荐 WHERE TABLE_TYPE="BASE TABLE" AND TABLE_CATALOG="Northwind""; 源代码网推荐 源代码网推荐 List<string> tableNames = new List<string>(); 源代码网推荐 using (IDataReader reader = command.ExecuteReader()) 源代码网推荐 { 源代码网推荐 while (reader.Read()) 源代码网推荐 { 源代码网推荐 tableNames.Add(reader["TABLE_NAME"].ToString()); 源代码网推荐 } 源代码网推荐 } 源代码网推荐 return tableNames.ToArray(); 源代码网推荐 } 源代码网推荐 源代码网推荐 /// <summary> 源代码网推荐 /// 生成创建数据库表结构的 SQL 语句。 源代码网推荐 /// </summary> 源代码网推荐 private static string GenerateTableSchemaSql(IDbConnection connection, string queryString) 源代码网推荐 { 源代码网推荐 StringBuilder tableSql = new StringBuilder(); 源代码网推荐 源代码网推荐 IDbCommand command = connection.CreateCommand(); 源代码网推荐 command.CommandText = queryString; 源代码网推荐 源代码网推荐 try 源代码网推荐 { 源代码网推荐 /* 获取查询结果各列的元数据 */ 源代码网推荐 DataTable schemaTable = null; 源代码网推荐 using (IDataReader reader = command.ExecuteReader(CommandBehavior.KeyInfo)) 源代码网推荐 { 源代码网推荐 schemaTable = reader.GetSchemaTable(); 源代码网推荐 } 源代码网推荐 源代码网推荐 /* 生成创建表定义语句 */ 源代码网推荐 string tableName = schemaTable.Rows[0]["BaseTableName"].ToString(); 源代码网推荐 tableSql.Append("CREATE TABLE [").Append(tableName).AppendLine("] ("); 源代码网推荐 源代码网推荐 /* 生成各列的定义语句 */ 源代码网推荐 string columnName; 源代码网推荐 string allowDBNull; 源代码网推荐 DataRow row; 源代码网推荐 bool hasKey = false; 源代码网推荐 StringBuilder sbPKFields = new StringBuilder(); 源代码网推荐 for (int i = 0; i < schemaTable.Rows.Count; i++) 源代码网推荐 { 源代码网推荐 if (i != 0) tableSql.AppendLine(","); 源代码网推荐 源代码网推荐 row = schemaTable.Rows[i]; 源代码网推荐 columnName = (string)row["ColumnName"]; 源代码网推荐 allowDBNull = ((bool)row["AllowDBNull"] == true ? "NULL" : "NOT NULL"); 源代码网推荐 源代码网推荐 if ((bool)row["IsKey"]) 源代码网推荐 { 源代码网推荐 sbPKFields.AppendFormat("[{0}],", columnName); 源代码网推荐 hasKey = true; 源代码网推荐 } 源代码网推荐 tableSql.AppendFormat(" [{0}] {1} {2}", columnName, GetSqlCeDataType(row), allowDBNull); 源代码网推荐 } 源代码网推荐 源代码网推荐 /* 生成主键约束语句 */ 源代码网推荐 if (hasKey) 源代码网推荐 { 源代码网推荐 string pkFields = sbPKFields.ToString().TrimEnd(","); 源代码网推荐 tableSql.AppendLine(","); 源代码网推荐 tableSql.Append(" CONSTRAINT PK_").Append(tableName).Append(" PRIMARY KEY(").Append(pkFields).AppendLine(")"); 源代码网推荐 } 源代码网推荐 tableSql.AppendLine(");"); 源代码网推荐 } 源代码网推荐 catch (Exception ex) 源代码网推荐 { 源代码网推荐 Debug.WriteLine(ex); 源代码网推荐 } 源代码网推荐 源代码网推荐 return tableSql.ToString(); 源代码网推荐 } 源代码网推荐 源代码网推荐 /// <summary> 源代码网推荐 /// 从 ColumnSchemaRow 获取 SQL Server CE 数据类型。 源代码网推荐 /// </summary> 源代码网推荐 private static string GetSqlCeDataType(DataRow columnSchemaRow) 源代码网推荐 { 源代码网推荐 Type type = columnSchemaRow["DataType"] as Type; 源代码网推荐 string dataType = GetSqlCeNativeType(type); 源代码网推荐 switch (dataType) 源代码网推荐 { 源代码网推荐 case "numeric": 源代码网推荐 Int16 precision = (Int16)columnSchemaRow["NumericPrecision"]; 源代码网推荐 Int16 scale = (Int16)columnSchemaRow["NumericScale"]; 源代码网推荐 if (precision != 0 && scale != 0) 源代码网推荐 { 源代码网推荐 dataType = string.Format("{0}({1},{2})", dataType, precision, scale); 源代码网推荐 } 源代码网推荐 break; 源代码网推荐 case "nvarchar": 源代码网推荐 int columnSize = (int)columnSchemaRow["ColumnSize"]; 源代码网推荐 if (columnSize > 4000) 源代码网推荐 { 源代码网推荐 dataType = "ntext"; 源代码网推荐 } 源代码网推荐 else 源代码网推荐 { 源代码网推荐 dataType = string.Format("{0}({1})", dataType, columnSize); 源代码网推荐 } 源代码网推荐 break; 源代码网推荐 } 源代码网推荐 return dataType; 源代码网推荐 } 源代码网推荐 源代码网推荐 /// <summary> 源代码网推荐 /// 从 .NET 数据类型获取对应的 SQL Server CE 类型名称。 源代码网推荐 /// </summary> 源代码网推荐 private static string GetSqlCeNativeType(Type systemType) 源代码网推荐 { 源代码网推荐 string typeName = systemType.ToString(); 源代码网推荐 switch (typeName) 源代码网推荐 { 源代码网推荐 case "System.Boolean": 源代码网推荐 return "bit"; 源代码网推荐 case "System.Byte": 源代码网推荐 return "tinyint"; 源代码网推荐 case "System.Byte[]": 源代码网推荐 return "image"; 源代码网推荐 case "System.DateTime": 源代码网推荐 return "datetime"; 源代码网推荐 case "System.Decimal": 源代码网推荐 return "numeric"; 源代码网推荐 case "System.Double": 源代码网推荐 return "float"; 源代码网推荐 case "System.Guid": 源代码网推荐 return "uniqueidentifier"; 源代码网推荐 case "System.Int16": 源代码网推荐 return "smallint"; 源代码网推荐 case "System.Int32": 源代码网推荐 return "integer"; 源代码网推荐 case "System.Int64": 源代码网推荐 return "bigint"; 源代码网推荐 case "System.Single": 源代码网推荐 return "real"; 源代码网推荐 case "System.String": 源代码网推荐 return "nvarchar"; 源代码网推荐 default: 源代码网推荐 throw new ApplicationException(string.Format("找不到 {0} 类型对应的 SQL Server CE 数据类型。", typeName)); 源代码网推荐 } 源代码网推荐 } 源代码网推荐 } 源代码网推荐 } 源代码网推荐 总结:阅读完本文,相信你已经了解了如何利用 ADO.NET 的 IDataReader.GetSchemaTable 方法获得服务器端数据库表的元数据,并用于生成对应的创建 SQL Server CE 数据库表的 SQL 语句。本系列文章可能还会有更精彩的续篇,我会将平时积累的关于 SQL Server CE 数据导入的一些经验充实到本系列中。 源代码网推荐 源代码网推荐 示例代码下载:sqlce_data_import3.rar 源代码网推荐 http://www.cnblogs.com/Files/upto/sqlce_data_import3.rar 做人要厚道,请注明转自酷网动力(www.ASPCOOL.COM)。 源代码网推荐 源代码网供稿. |
