TypeCast克服接口限制?

时间:2016-11-18 01:14:40

标签: c# interface

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

为了克服接口的限制,输入接口对象是不错的做法?

实施例

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

2 个答案:

答案 0 :(得分:3)

不,这不是好习惯。

首先,除非绝对必要,否则不应该低估。如果需要仅由接口实现提供的值,请从该实现开始。在您的情况下,如果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
    }
 }

当然,只使用界面是首选选项,但在这种情况下,您可能很难控制它。

答案 1 :(得分:0)

布拉德利的回答是正确而简洁的。我还要根据您的代码添加它,访问存储过程参数并不一定是将您耦合到特定实现的因素。实现数据库无关数据访问代码的我最喜欢的工具之一是 Dapper 的奇妙魔力。信不信由你,它是运行Stack Overflow的数据访问库!

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

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#类型(这可能会消除你在几个区域中输入类型的需要) )。

通过硬铸(使用parentheses)或软铸造,至少在我的书中,都被认为是代码气味(虽然我同意布拉德利 - 如果你必须软化)。只有在少数几个特定领域才有人绝对需要这样做。对于一个简单的应用程序,随时可以完全依赖您的数据库,并随心所欲。对于任何非平凡的企业应用程序,对数据库采取硬依赖最终将锁定您的应用程序堆栈并使未来的重构处于危险之中。