如何从 IDbConnection “继承” - 只需添加一个属性(DatabaseType)
Posted
技术标签:
【中文标题】如何从 IDbConnection “继承” - 只需添加一个属性(DatabaseType)【英文标题】:How to 'inherit' from IDbConnection - just add one property (DatabaseType) 【发布时间】:2012-11-28 05:40:15 【问题描述】:你如何继承IDbConnection
?我想添加一个属性(DatabaseType
,例如 MS Access、SQL server、Paradox...)。据我所知IDbConnection
是一个接口,因此我相信他们希望我实现整个接口继承链中的所有成员。这似乎是很多工作。将一个属性添加到 IDbConnection
的最佳方法是什么?
更新 我想做的是这个。我有三种我经常使用的方法:ExecuteReader、ExecuteNonQuery、ExecuteNonQueryGetIdentity。它们被大量使用并具有参数(IDbConnection Conn、字符串 SQLString、object[] SQLParams)。我认为将 DatabaseType 添加到这三个方法和我所有项目方法的最佳方法是“覆盖” IDbConnection,这样我只需更新项目中的一行代码。
我想知道 DatabaseType,因为在添加参数和构建 IDbCommand 时我会做一些不同的事情。专门针对 DateTime。
例如:
public static System.Data.IDataReader ExecuteReader(System.Data.IDbConnection Conn, string SQL, object[] SQLParams)
// return IDataReader from connection, SQL string and Params. Params can be null.
using (var cmd = Conn.CreateCommand())
cmd.CommandText = SQL;
AddParametersToCommand(cmd, SQLParams); // add parameters to IDbCommand object if params not null
return cmd.ExecuteReader();
private static readonly Regex regParameters = new Regex(@"@\w+", RegexOptions.Compiled);
public static void AddParametersToCommand(IDbCommand Cmd, object[] Parameters)
/* Creates and ads unique parameters to an IDbCommand object to the CommandText SQL string.
* Tested types with SQL Update statement in MS Access/SQL Server: boolean, int, DateTime, text
* Parameter names in CommandText must start with the '@' char and can be any unique word (letter or number).
* E.g. calling code: cmd.CommandText = "Select * From SiteUser Where Site > @1 And User > @NewParam"
*
* http://www.codeproject.com/Articles/15542/IDbDataParameter-error-in-NET re: some DateTime issues
*/
if (Parameters != null && Parameters.Length > 0)
MatchCollection cmdParams = regParameters.Matches(Cmd.CommandText);
var paramNames = new List<String>();
foreach (var el in cmdParams)
if (!paramNames.Contains(el.ToString())) // only add unique parameter names
paramNames.Add(el.ToString());
IDbDataParameter dp;
var dbType = GetDatabaseType(Cmd.Connection);
for (int n = 0; n < Parameters.Length; n++)
var param = Parameters[n];
dp = Cmd.CreateParameter();
dp.ParameterName = paramNames[n];
TypeCode myTypeCode = Type.GetTypeCode(param.GetType());
if (myTypeCode == TypeCode.DateTime) // this workaround is needed for MS Access and SQL Server
if (dbType == DatabaseType.Access)
dp.DbType = DbType.DateTime; // set dates as DbType.DateTime for MS Access and Paradox
dp.Value = param.ToString(); // Convert.ToDateTime(param).ToString("yyyy-MM-dd hh:mm:ss"));
//Note: MS access cannot store years before December 30, 1899. They will be stored for some other year.
// for example. Jan 1 0001 will be stored as 2001.
else if (dbType == DatabaseType.MSSql)
dp.DbType = DbType.DateTime2; // set dates as DbType.DateTime2 for SQL Server
dp.Value = param.ToString();
else
dp.Value = param;
Cmd.Parameters.Add(dp);
// for n
// if
【问题讨论】:
您想这样做的原因是什么?根据您想要的原因,可能有不同的方法来做到这一点。 接口不是继承的——它们是被实现的。你到底想做什么?如果您只想要一个包含IDbConnection
中所有内容但使用DatabaseType
的课程,您应该选择史蒂夫的答案。
【参考方案1】:
您可以使用DatabaseType
属性创建新接口MyDbConnection
,但现有的IDbConnection
实现都不会实现您的接口。
我认为您不应该关心您使用的是IDbConnection
的哪个实现(MS Access、SQL 服务器、Paradox 等)。这就是我们有这个抽象和DbProviderFactory
类的原因,它们完全是我们正在使用的数据库的抽象类型。
顺便说一句,您始终可以检查IDbConnection
实例的类型,以查看您正在使用哪个实现(如果您真的需要它)。您的另一个选择(如果您真的需要该属性) - 在 IDbConnection
实例上创建装饰器:
public class MyDbConnection : IDbConnection
private IDbConnection _connection;
public MyDbConnection(IDbConnection connection)
_connection = connection;
// here goes your property
public string DatabaseType get; set;
public void Close()
_connection.Close();
public IDbTransaction BeginTransaction(IsolationLevel il)
return _connection.BeginTransaction(il);
// implement other IDbConnection members by delegating work to _connection
你可以在任何地方使用这个装饰器作为IDbConnection
,但你的属性也将可用。
【讨论】:
在更新的问题详细信息中,我解释了为什么在更新 MS Access、SQL Server、Paradox 等中的早期 DateTime 字段时我需要了解基础数据库类型(而不仅仅是连接类型)。 @user610064 很有趣 - 您的应用程序使用1899
之前的日期?
好吧,我只承认过去的时间。在某些情况下,我们一直在使用 DateTime 来存储经过的时间……当时它非常方便。现在将 MS Access 转换为 SQL Server...
@user610064 如果您仅对 DateTime 有问题,则只需提取将创建 DbParameter 的方法,即AddParameter(command, name, object)
。并从您的 ExecuteXXX 方法中调用该方法。【参考方案2】:
DbConnection 实现接口 IDbConnection。您可以扩展它(它必须实现所有接口方法)
【讨论】:
以上是关于如何从 IDbConnection “继承” - 只需添加一个属性(DatabaseType)的主要内容,如果未能解决你的问题,请参考以下文章
小巧玲珑。 IDbConnection 和 IDbTransaction
将 BeginTransaction 与 Dapper.IDbConnection 一起使用的正确方法