c # set datarow DateTime поле в зависимости от типа БД - PullRequest
1 голос
/ 11 июля 2011

Я пишу программу, которая может использовать БД SQLite или БД MySql в качестве альтернативы. (В зависимости от того, нужно ли его использовать нескольким пользователям, сетевой инфраструктуре и т. Д.)

Я написал общий интерфейс DBType и два класса, которые реализуют его в зависимости от типа БД. Есть функция DataTable GetAllRows(tableName), которая, как вы ожидаете, просто извлекает все строки таблицы и заполняет System.Data.DataTable. Для SQLite я использовал соединитель SQLIte и для MySql я использовал MySql разъем .

Теперь проблема в том, что когда я читаю строки с помощью специального DataReader (поставляемого из соединителей), DataTable устанавливает типы столбцов с типами, возвращаемыми из этих соединителей. Соединитель SQLite использует System.DateTime для полей DateTime, MySql использует MySql.Data.Types.MySqlDateTime.

Я также реализовал структуру провайдера сущностей, поэтому я неявно преобразую каждый полученный DataRow в сущность (по требованию), чтобы поля DateTime превратились в поле DateTime в соответствующий класс сущности.

Например, предположим, что в БД есть таблица:

userTable: 
field "userName" as string,
field "date" as DateTime

с одной строкой:

"asd" 2000/01/01

Я вызываю GetAllRows для этой таблицы, теперь у меня есть DataTable с 2 столбцами: первый столбец является строковым полем, второй столбец - System.DateTime или MySqlDateTime в зависимости от типа БД, которую я использую для этого прогона.

Строка будет преобразована в сущность

class userTableEntity
{
    string name;
    DateTime data;

    /* methods... */

    implicit operator userTableEntity(DataRow row);
}

userTableEntity u = datarow; //uses the implicit operator

Если я хочу вернуться и преобразовать сущность в DataRow, я должен использовать что-то вроде этого:

MyDataRow[userFieldName] = entity.name;
MyDataRow[dataFieldName] = entity.data;

Если я использую SQLite, это не проблема. Если я использую MySql, строка MyDataRow[dataFieldName] = entity.data выдаст исключение типа, потому что MyDataRow[dataFieldName] имеет тип MySqlDateTime, а entity.data представляет собой System.DateTime

Конечно, я могу переключаться между SQLite / MySql перед назначением поля, но у меня есть что-то вроде 75 таблиц с большим количеством полей DateTime, поэтому я не хочу создавать случай переключения (или if) каждый раз по очевидным причинам.

Я пытался создать класс MyDateTime, который выполняет внутреннее преобразование с такими операторами:

implicit operator DateTime
implicit operator MySql.Data.Types.MySqlDateTime

но эти операторы никогда не будут вызваны, потому что тип выражения MyDataRow[dataFieldName] равен object, а не DateTime или MySqlDateTime! Также я не могу написать неявный оператор для объекта, потому что класс MyDateTime является подтипом объекта, поэтому он не разрешен.

Обратите внимание, что MySql.Data.Types.MySqlDateTime имеет несколько полезных методов:

public static explicit operator DateTime(MySqlDateTime val);
public DateTime GetDateTime();
public DateTime Value { get; }

и ктор:

public MySqlDateTime(DateTime dt);

Как я могу организовать код, чтобы сделать что-то вроде MyDataRow[dataFieldName] = entity.data без исключения? Я могу изменить тип entity.data, но не хочу каждый раз переключать регистр, и я предпочитаю поддерживать DataTable во время его чтения (без изменения типа в столбцах).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...