TypeCast克服接口限制

本文关键字:接口 克服 TypeCast | 更新日期: 2023-09-27 18:18:26

我正在使用IDbCommand和IDbDataParameter接口用于我的SQL db逻辑,但意识到由于接口限制,我无法获得sqlCommand.parameter["ID"] . value。

对接口对象进行类型强制转换以克服接口的限制是一种好做法吗?

例子
using (IDbCommand SqlCmd = CommandProvider.GetSPCommand(conn))
{
    // setup sqlcmd with output paramter and executenonquery ...
    ID = Convert.ToInt32(((SqlCommand)SqlCmd).Parameters["ID"].Value);
 }

TypeCast克服接口限制

不,这不是一个好的做法。

首先,除非绝对必要,否则不应该向下转换。如果您需要一个仅由接口实现提供的值,请从该实现开始。在您的示例中,如果CommandProvider.GetSPCommand返回SqlCommand,则只需执行:
using (SqlCommand SqlCmd = CommandProvider.GetSPCommand(conn))
{
    // setup sqlcmd with output paramter and executenonquery ...
    ID = Convert.ToInt32(((SqlCommand)SqlCmd).Parameters["ID"].Value);
 }
如果

没有做到这一点,那么您就遇到了第二件错误的事情,即在检查是否安全之前进行强制转换。如果返回的项不是 SqlCommand,您的代码将抛出InvalidCastException。相反,使用as操作符检查:

using (IDbCommand SqlCmd = CommandProvider.GetSPCommand(conn))
{
    SqlCommand fullSqlCommand = SqlCmd as SqlCommand;
    if (fullSqlCommand != null)
    {
       // setup sqlcmd with output paramter and executenonquery ...
       ID = Convert.ToInt32(fullSqlCommand.Parameters["ID"].Value);
    }
    else
    {
        //Some failsafe
    }
 }

当然,只使用接口是最好的选择,但是当您无法控制它时,这可能会很困难。

Bradley的回答既正确又简洁。我还要补充一点,根据您的代码,访问存储过程参数不一定是将您与特定实现结合在一起的因素。我最喜欢的实现数据库独立的数据访问代码的工具之一是Dapper的奇妙魔力。信不信由你,运行Stack Overflow的是数据访问库!

从他们的文档中,您可以使用以下代码添加和访问参数:

var p = new DynamicParameters();
p.Add("@a", 11);
p.Add("@b", dbType: DbType.Int32, direction: ParameterDirection.Output);
p.Add("@c", dbType: DbType.Int32, direction: ParameterDirection.ReturnValue);
cnn.Execute("spMagicProc", p, commandType: CommandType.StoredProcedure); 
int b = p.Get<int>("@b");
int c = p.Get<int>("@c"); 

然后您可以继续针对IDbCommand, IDbConnection等抽象进行编码。Dapper有一种高性能的方法,可以从数据库中获取值,并轻松地将它们转换为c#类型(这可能会在某些地方消除类型强制转换的需要)。

通过硬类型转换(使用括号)或软类型转换,至少在我的书中,都被认为是代码气味(尽管我同意Bradley的观点-如果你必须使用软类型转换)。只有在少数特定领域,人们才绝对需要这样做。对于一个微不足道的应用程序,可以完全依赖于数据库,然后继续你的快乐之路。对于任何重要的企业应用程序,对数据库的硬依赖最终会使你的应用程序堆栈被供应商锁定,并使未来的重构面临风险。