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 数据类型。这个方法的代码如下所示:
///
/// 从 .NET 数据类型获取对应的 SQL Server CE 类型名称。
///
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));
}
} 当然,仅仅知道列的数据类型还不够,我们需要为某些列的数据类型加上长度、精度或小数位数等列大小信息。可以通过下面的方法实现:
///
/// 从 ColumnSchemaRow 获取 SQL Server CE 数据类型。
///
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"];
Int32 colsize = (Int32)columnSchemaRow["ColumnSize"];
if (precision != 0 && scale != 0 && scale != 255)
{
dataType = string.Format("{0}({1},{2})", dataType, precision, scale);
}
else if (scale == 255 && colsize == 8)
{
dataType = "money";
}
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 语句,生成结果如下:
// 从 SQL Server 信息架构视图获取 Northwind 数据库所有表的名称
command.CommandText = @"SELECT * FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_TYPE='BASE TABLE' AND TABLE_CATALOG='Northwind'";
List tableNames = new List();
using (IDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
tableNames.Add(reader["TABLE_NAME"].ToString());
}
}
return tableNames.ToArray();
} 有了 GetTableNames 方法,我们就可以一次性对 Northwind 数据库的所有用户表生成相应的创建 SQL Server CE 数据库表结构的 SQL 语句。
总结:阅读完本文,相信你已经了解了如何利用 ADO.NET 的 IDataReader.GetSchemaTable 方法获得服务器端数据库表的元数据,并用于生成对应的创建 SQL Server CE 数据库表的 SQL 语句。本系列文章可能还会有更精彩的续篇,我会将平时积累的关于 SQL Server CE 数据导入的一些经验充实到本系列中。