我正在编写一个可以使用SQLite DB或MySql DB的程序。 (取决于是否必须使用多个,网络基础设施等......)
我编写了一个通用的DBType接口和两个基于DB类型实现它的类。有一个函数DataTable GetAllRows(tableName)
,正如您所期望的那样,它只是检索表的所有行并填充System.Data.DataTable。对于SQLite,我使用了SQLIte connector
对于MySql,我使用了MySql connector。
现在的问题是,当我使用专门的DataReader(从连接器提供)读取行时,DataTable会使用从此连接器返回的类型设置列类型。 SQLite连接器使用System.DateTime
作为DateTime字段,MySql使用MySql.Data.Types.MySqlDateTime
。
我还实现了一个实体提供程序框架,因此我将每个检索到的DataRow隐式转换为Entity(按需),因此DateTime字段将成为相应实体类的DateTime字段。
例如,假设在DB中有一个表:
userTable: field "userName" as string, field "date" as DateTime
有一行:
"asd" 2000/01/01
我为此表调用GetAllRows,现在我有一个包含2列的DataTable: 第一列是字符串字段,第二列是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字段,所以我不想每次出于显而易见的原因创建一个switch case(或if)。
我已经尝试创建一个MyDateTime类,它使用这些运算符执行内部转换:
implicit operator DateTime
implicit operator MySql.Data.Types.MySqlDateTime
但是这些运算符永远不会被调用,因为表达式MyDataRow[dataFieldName]
的类型是object
而不是DateTime
或MySqlDateTime
!我也不能写对象的隐式运算符,因为MyDateTime类是object的子类型,所以不允许这样做。
请注意MySql.Data.Types.MySqlDateTime
有一些有用的方法:
public static explicit operator DateTime(MySqlDateTime val);
public DateTime GetDateTime();
public DateTime Value { get; }
和ctor:
public MySqlDateTime(DateTime dt);
如何安排代码执行类似MyDataRow[dataFieldName] = entity.data
的操作而无例外?我可以更改entity.data的类型,但我不想每次都做一个switch case,我更喜欢在读取时维护DataTable(列中没有类型更改)。