2013-03-11 88 views
0

我有一个隐藏不同ADO.NET提供者的差异,并有大量的代码就像一个dll:如何动态地处理对dll的依赖关系?

private static void AppendProviderSpecificParameterCmdStr(StringBuilder sb, DbCommand cmd, string fieldNameToUse, ComparisonOperator oprtr, string parameterName) 
{ 
    if (cmd is System.Data.OracleClient.OracleCommand || cmd is Oracle.DataAccess.Client.OracleCommand) 
    { 
     sb.AppendFormat("{0}{1}:{2}", fieldNameToUse, GetComparisonOperatorStr(oprtr, cmd), parameterName); 
    } 
    else if (cmd is SqlCommand) 
    { 
     sb.AppendFormat("{0}{1}@{2}", fieldNameToUse, GetComparisonOperatorStr(oprtr, cmd), parameterName); 
    } 
    else if (cmd is OleDbCommand) 
    { 
     sb.AppendFormat("{0}{1}?", fieldNameToUse, GetComparisonOperatorStr(oprtr, cmd)); 
    } 
    else 
    { 
     throw new Exception(string.Format("Wrong database command type: {0},", cmd.GetType())); 
    } 
} 

其中比较运营商是我自己的枚举。

Oracle.DataAccess存在于所有具有oracle客户机的机器上,并且此代码对我的需求已满足。但是现在我遇到了只有SqlClient的情况,他们根本就不需要oracle。所以我的代码只有在我复制Oracle.DataAccess.dll时才有效,这自然是一个可怕的解决方案。这应该如何以正确的方式完成?

谢谢-matti

回答

1

我不会调用依赖于dll一个可怕的解决方案。您的解决方案支持Oracle,因此您的解决方案中有一个Oracle dll - 它就是这样。

也就是说,有些事情可以抽象出命令类型。

One - 创建实现接口的完整数据访问方法。我将其分类为更多通用数据访问的帮助程序或实用程序方法。您可以改为将具体接口声明为域名,例如客户 - 例如ICustomerDA。在你的情况下,你会有3个ICustomerDA.Insert的实现,并将数据库细节埋在里面。你的主要代码只需要了解ICustomerDA。这可能是我在更大的解决方案中所要做的,因为RDBMS之间的差异和功能远远超出了参数声明。

二 - 如果你想坚持更多的帮助/实用的想法,你可以创建一个接口,为数据库对象的包装,说IDBCommand。 IDbCommand的会躲在底层的命令对象,然后实现有.AppendProviderSpecificParameterCmdStr方法,这样可以让你做什么样的具体实现:

OracleDbHelper : IDbCommand... 
    public void AppendProviderSpecificParameterCmdStr(...){ 
    sb.AppendFormat("{0}{1}:{2}", fieldNameToUse, GetComparisonOperatorStr(oprtr, cmd), parameterName); 
    } 

IDBCommand cmd = DAFactory.GetCommand(); 
cmd.AppendProviderSpecificParameterCmdStr(... 

到这两种解决方案的核心是由一个共同的接口引用您的主要项目而不是单个类型。一旦你这样做了,你可以在你的工厂中使用反射,或者更好,类似MEF来创建实际类型。

+0

感谢您的回答。我必须在稍后检查。我称它为可怕的,因为将Oracle.DataAccess.dll复制到没有oracle的客户对我而言并不好。它也可能涉及一些法律问题? – 2013-03-13 07:05:15

+0

我完全理解你的意思。但是,我也发现,近些年来,语义或“最佳实践”被放在编译和运行没有问题的代码之前。您可能会对授权有所了解,但我怀疑这是一个问题:“在大多数情况下,Oracle不会收取任何费用来分发Oracle客户端,也不会收取第三方应用程序的ODP.NET费用。但是,最好咨询许可协议,您从中获得Oracle软件的权利....“http://www.oracle.com/technetwork/database/windows/faq-093106.html#distribute – 2013-03-14 13:46:35

+0

谢谢!我忘了这个答案,但这实际上有点像我上周做的事情(包装)。也许下意识:)我的解决方案是这样的,我把这个问题:http://stackoverflow.com/questions/21988358/what-does-a-using-statement-without-variable-do-when-disposing – 2014-02-25 09:10:49

0

所以我的代码只能如果我复制Oracle.DataAccess.dll

除非你有本地OCI的DLL,例如,因为你已经安装了Oracle客户端。

为避免强制用户安装完整的Oracle客户端,您可以将Oracle客户端的DLL与应用程序一起分发。如果用户从不选择连接到Oracle,这些DLL永远不会被调用,只是静静地坐在那里,不会造成任何麻烦。

有关如何分配内容以及如何涵盖32位和64位的一些提示,请参阅this post

我们有一个本土的抽象层,目前与Oracle和MS SQL Server一起工作(并且可以移植到任何带有体面的ADO.NET提供者的DBMS),而且这个系统迄今为止工作得非常好。

+0

没有。我不需要安装其他dll。这是尝试和证明。只有Oracle.DataAccess.dll在没有任何类型的oracle客户端的机器上工作正常。 – 2014-02-12 12:24:50

+1

@matti Oracle.DataAccess.dll是旧的“混合模式”ODP.NET,它需要本机DLL。也许你的意思是Oracle.ManagedDataAccess.dll(新的“完全托管”ODP.NET)? – 2014-02-12 13:53:01

+0

对于迟到的回答感到抱歉。这没有原生的DLL工作。只复制Oracle.DataAccess.dll。请注意,它并未在SQL Server环境中使用它。我无法解释这一点或知道任何关于。这个托管的DLL对我来说是全新的。我得看看这个。谢谢。 – 2014-02-25 09:07:54