为什么MySQL Connector.NET无法正确地将类型映射到C#类型?

时间:2015-08-24 18:32:46

标签: c# mysql powershell mysql-connector

MySQL表定义:

CREATE TABLE `table` (
  `id` tinyint(1) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Auto-increment ID',
  `data_provider_id` tinyint(1) unsigned NOT NULL COMMENT 'Data provider ID',
  `is_active` bit(1) NOT NULL DEFAULT b'1' COMMENT '0 = retired source',
  PRIMARY KEY (`id`),
  KEY `DATA_PROVIDER_ID` (`data_provider_id`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8

C#代码:

public static class MySqlConnector
{
    public static DataTable QueryDatabase(
            MySqlConnection mysqlConnection,
            string mysqlQuery)
    {
        MySqlCommand mysqlCommand = new MySqlCommand(mysqlQuery, mysqlConnection);
        MySqlDataReader mysqlDataReader = mysqlCommand.ExecuteReader();

        DataTable dataTable = new DataTable();
        dataTable.Load(mysqlDataReader);

        return dataTable;
    }
}

...

mysqlQuery = @"
    SELECT
      `id`,
      `data_provider_id`,
      `is_active`
    FROM
      `{0}`;
    ";
mysqlQuery = String.Format(mysqlQuery, tableName);
DataTable dt = MySqlConnector.QueryDatabase(mysqlConnection, mysqlQuery);

现在,当我在GetType()字段上拨打dt时,表示idInt32(而不是Byte),data_provider_idByte(令人惊讶的正确)和is_activeUint64(而不是Boolean)。

情况变得更糟。我有另一个表格,其中id字段为int(1) unsigned,而QueryDatabase()仍将其作为已签名的int返回。

用于快速测试的PowerShell代码:

# Importing MySQL Connector.NET DLL.
$sMySqlServer = "server"
$sPath = "\\{0}\Connector.NET 6.9.7\Assemblies\v4.5\MySql.Data.dll" `
    -f $sMySqlServer
Add-Type -Path $sPath

# Creating MySQL connection.
$sMySqlUser = "user"
$sMySqlPassword = "password"
$sMySqlDatabase = "test"

$sMySqlConnectionString = "server={0};uid={1};pwd={2};database={3};" `
    -f $sMySqlServer, $sMySqlUser, $sMySqlPassword, $sMySqlDatabase
$oMySqlConnection = New-Object -TypeName MySql.Data.MySqlClient.MySqlConnection
$oMySqlConnection.ConnectionString = $sMySqlConnectionString
$oMySqlConnection.Open()

# Getting raw data.
$sMySqlQuery = "SELECT * FROM `table` ;"
$oMySqlCommand = New-Object -TypeName `
    MySql.Data.MySqlClient.MySqlCommand($sMySqlQuery, $oMySqlConnection)
$oMySqlDataReader = $oMySqlCommand.ExecuteReader()
$oDataTable = New-Object -TypeName System.Data.DataTable
$oDataTable.Load($oMySqlDataReader)

$oDataTable | Get-Member

输出:

   TypeName: System.Data.DataRow

Name              MemberType            Definition                                        
----              ----------            ----------                                        
AcceptChanges     Method                void AcceptChanges()                              
BeginEdit         Method                void BeginEdit()                                  
CancelEdit        Method                void CancelEdit()                                 
ClearErrors       Method                void ClearErrors()                                
Delete            Method                void Delete()                                     
EndEdit           Method                void EndEdit()                                    
Equals            Method                bool Equals(System.Object obj)                    
GetChildRows      Method                System.Data.DataRow[] GetChildRows(string relat...
GetColumnError    Method                string GetColumnError(int columnIndex), string ...
GetColumnsInError Method                System.Data.DataColumn[] GetColumnsInError()      
GetHashCode       Method                int GetHashCode()                                 
GetParentRow      Method                System.Data.DataRow GetParentRow(string relatio...
GetParentRows     Method                System.Data.DataRow[] GetParentRows(string rela...
GetType           Method                type GetType()                                    
HasVersion        Method                bool HasVersion(System.Data.DataRowVersion vers...
IsNull            Method                bool IsNull(int columnIndex), bool IsNull(strin...
RejectChanges     Method                void RejectChanges()                              
SetAdded          Method                void SetAdded()                                   
SetColumnError    Method                void SetColumnError(int columnIndex, string err...
SetModified       Method                void SetModified()                                
SetParentRow      Method                void SetParentRow(System.Data.DataRow parentRow...
ToString          Method                string ToString()                                 
Item              ParameterizedProperty System.Object Item(int columnIndex) {get;set;},...
data_provider_id  Property              byte data_provider_id {get;set;}                  
id                Property              int id {get;set;}                                 
is_active         Property              uint64 is_active {get;set;}                       

SSDD

[解决]尽管wchiquito的回答并不是一个完整的解决方案,但它仍然朝着正确的方向推动我。 DataTable.Load()中的类型转换确实有些破坏,因此您需要在调用Load()之前向DataTable添加基本架构。以下可能并不完美,但它对我有用:

private static void TranslateSchema(
        DataTable dataTable,
        MySqlDataReader mysqlDataReader)
{
    string columnName;
    Type columnType;

    mysqlDataReader.Read();

    for (int i = 0; i < mysqlDataReader.FieldCount; i++)
    {
        columnName = mysqlDataReader.GetName(i);
        columnType = mysqlDataReader.GetFieldType(i);

        dataTable.Columns.Add(columnName, columnType);
    }
}

bit(1)仍然成为UInt64,但我可以忍受。

1 个答案:

答案 0 :(得分:1)

使用什么版本的Connector / Net?对于版本6.9.7,我无法重现该问题。

MySQL的:

CREATE TABLE `table` (
    `id` TINYINT(1) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'Auto-increment ID',
    `data_provider_id` TINYINT(1) UNSIGNED NOT NULL COMMENT 'Data provider ID',
    `is_active` BIT(1) NOT NULL DEFAULT b'1' COMMENT '0 = retired source',
    `id_temp` INT(1) UNSIGNED DEFAULT NULL,
    PRIMARY KEY (`id`),
    KEY `DATA_PROVIDER_ID` (`data_provider_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

C#:

...
DataTable schema = dr.GetSchemaTable();
...

结果:

`id`               -> System.Byte
`data_provider_id` -> System.Byte
`is_active`        -> System.UInt64
`id_temp`          -> System.UInt32

6.2.3.1 Collections

...
DataTable table = mysqlConnection.GetSchema("DataTypes");
...

结果:

TypeName = BIT
...
CreateFormat = BIT
... 
DataType = System.UInt64
...
============================
TypeName = TINY INT
...
CreateFormat = TINYINT UNSIGNED
...
DataType = System.Byte
...
============================
TypeName = INT
...
CreateFormat = INT UNSIGNED
...
DataType = System.UInt32
...