数据库类型无法构建。您必须配置容器以提供此值(EntLib 5 + ODP.NET)。

7

我使用ODP.NET和Enterprise Library 4.1,在vs2008中,一切正常。

现在,迁移到使用ODP.NET Oracle.DataAccess 4.112.2.0和Enterprise Library 5.0.414.0, 在vs2010、.net 4.0中。

Oracle.DataAccess 4.112.2.0 EnterpriseLibrary 5.0.414.0

最近将Enterprise Library版本从4.1升级到5.0后,我们遇到了以下错误:

"The type Database cannot be constructed. You must configure the container to supply this value."

Microsoft.Practices.ServiceLocation.ActivationException: 尝试获取类型Database的实例时出现激活错误,键为“ConnectionStrings.Oracle.xxx” ---> Microsoft.Practices.Unity.ResolutionFailedException: 解析依赖项失败,类型 =“Microsoft.Practices.EnterpriseLibrary.Data.Database”,名称 =“ConnectionStrings.Oracle.xxx”。异常出现在:解析期间。异常是:InvalidOperationException-无法构造类型Database。必须配置容器以提供此值。

参考 EntLib 论坛:http://entlib.codeplex.com/discussions/215290

有关此问题的任何解决方案吗?

我的配置:

<configSections>

<section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=709072f976b4c05b"/>

<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings,Microsoft.Practices.EnterpriseLibrary.Data, Version=5.0.414.0, Culture=neutral, PublicKeyToken=709072f976b4c05b" />
</configSections>

<dataConfiguration defaultDatabase="ConnectionStrings.Oracle.xxx"/>

<connectionStrings>

<add name="ConnectionStrings.Oracle.xxx" connectionString="DATA SOURCE=des;PASSWORD=zzz;PERSIST SECURITY INFO=True;USER ID=aaa;"
providerName="Oracle.DataAccess.Client" />

我的代码

 var key = "ConnectionStrings.Oracle.xxx";

            Database db = Microsoft.Practices.EnterpriseLibrary.Common.Configuration.EnterpriseLibraryContainer.Current.GetInstance<Database>(key); //~(EntLib 5 recommended)


            using (DbCommand cm = db.GetStoredProcCommand("TBL_FRKDATA.TBL_FRKDATA_FND_ALL"))
            {
                cm.Parameters.Add(CreateCursorParameter("P_REFCURSOR"));

                // Using "using" will cause both the DataReader and connection to be 
                // closed. (ExecuteReader will close the connection when the 
                // DataReader is closed.)
                using (IDataReader dataReader = db.ExecuteReader(cm))
                {
                    while (dataReader.Read())
                    {
                        builder.Add(dataReader);
                    }
                    return builder.EntityList;

                }
            } 

完整的错误堆栈跟踪
Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.GuardTypeIsNonPrimitive(IBuilderContext context, SelectedConstructor selectedConstructor) Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.PreBuildUp(IBuilderContext context) Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlanCreatorPolicy.CreatePlan(IBuilderContext context, NamedTypeBuildKey buildKey) Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable1 resolverOverrides) Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable1 resolverOverrides) Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name, ResolverOverride[] resolverOverrides) Microsoft.Practices.Unity.UnityServiceLocator.DoGetInstance(Type serviceType, String key) Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key) Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key) Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance[TService](String key)

更新

这段代码对我有效:

    [TestMethod]
    public void Conectar_con_EntLib_y_OdpNet_Test()
    {
        var key = "ConnectionStrings.Oracle.xxx";

        string connectionString = ConfigurationManager.ConnectionStrings[key].ConnectionString;
        string providerName = ConfigurationManager.ConnectionStrings[key].ProviderName;

        //Database db = Microsoft.Practices.EnterpriseLibrary.Common.Configuration.EnterpriseLibraryContainer.Current.GetInstance<Database>(key);

        TestContext.WriteLine("connectionString: " + connectionString);
        TestContext.WriteLine("providerName: " + providerName);

        DbProviderFactory factory = DbProviderFactories.GetFactory(providerName);

        using (DbConnection connection = factory.CreateConnection())
        {
            connection.ConnectionString = connectionString;

            connection.Open();

            TestContext.WriteLine("Estado Conexión: " + connection.State);
            connection.Close();
        }



    }

解决方案:由Randy Levy提供(http://entlib.codeplex.com/discussions/215290
您不能使用Enterprise Library OracleDatabase与Oracle.DataAccess.Client提供程序。内置的OracleDatabase是硬编码为使用OracleClientFactory DbProviderFactory,而您想使用ODP.NET提供程序(Oracle.DataAccess.Client)。
最好的方法是让EntLibContrib Oracle ODP.NET数据提供程序工作,因为它应该支持您需要的所有内容,包括配置文件。
由于看起来您可以创建DbProviderFactory,因此您可以尝试使用具有ODP.NET OracleClientFactory的GenericDatabase,但我猜您会遇到特定Oracle功能(例如refcursor)的问题。
您可以直接使用它:
string connectionString = ConfigurationManager.ConnectionStrings["Connection String"].ConnectionString;
string providerName = ConfigurationManager.ConnectionStrings["Connection String"].ProviderName;

DbProviderFactory factory = DbProviderFactories.GetFactory(providerName);
var db = new GenericDatabase(connectionString, factory);

快速检查MSDN帖子。声明但是请记住,在.NET Framework 4.0版本中,OracleClient提供程序已被弃用,尽管它仍受Enterprise Library的支持。对于未来的开发,请考虑选择不同的Oracle驱动程序。 - Amar Palsapure
你是否查看过 https://dev59.com/4W865IYBdhLWcg3wBJwq 或者 https://dev59.com/eXE85IYBdhLWcg3wMAfc? - Amar Palsapure
System.Data.OracleClient.dll在.NET 4.0中已被弃用。但是ODP.NET(Oracle.DataAccess.dll)在.NET 4.0中得到支持。问题是使用了Oracle.DataAccess.dll 4.112.2.0和EntLib 5.0。 - Kiquenet
我使用了EntLib Config Wiz,当我添加Oracle连接字符串时,它会添加<section name="oracleConnectionSettings" type="Microsoft.Practices.EnterpriseLibrary.Data.Oracle.Configuration.OracleConnectionSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" /><oracleConnectionSettings>。你可以试试EntLib Config Wiz吗? - Amar Palsapure
2个回答

2

添加一个引用到

Microsoft.Practices.EnterpriseLibrary.Common
Microsoft.Practices.EnterpriseLibrary.Data
Microsoft.Practices.ServiceLocation

然后使用这行代码获取数据库:

var database = EnterpriseLibraryContainer.Current.GetInstance<Database>();

更多信息请参见:http://devstuffs.wordpress.com/2012/03/13/enterprise-library-5-with-odp-net/

这是关于使用ODP.NET的企业库5的更多信息。

我按照其他答案的建议进行了32位和64位的构建和IIS设置,但仍然出现错误。 - Grault

1

我曾经遇到同样的问题,解决方法是将应用程序池的“启用32位应用程序”设置为true。


这个问题出现在Windows服务上(所以不是特别的“启用32位应用程序”)。但是它是“编译为32位代码,服务器只有64位Oracle客户端”。我们重新编译了代码为64位,并能够部署到服务器并且它工作正常。 - dandarc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接