我在进行基本概念验证时遇到了很多困难,其中我通过 Entity Framework (6.2) 通过 Azure Functions 访问 Oracle DB (11g)。
先决条件: 已安装 ODT For Visual Studio 2017 以及 Azure Functions CLI/Core Tools。下面提到的所有内容完全通过 Visual Studio 2017 完成,而不是通过 Azure 门户。
取 1:
使用 Azure Functions 模板创建了一个新项目。
已安装的 NuGet 包 EntityFramework (6.2.0)、Oracle.ManagedDataAccess (12.2.1100) 和 Oracle.ManagedDataAccess.EntityFramework (12.2.1100)。注意:使用 Azure Functions 模板在项目中安装 NuGet 包时,这些包将添加到“依赖项”->“NuGet”下,而不是“引用”下。
向项目添加了 ADO.NET 实体数据模型。
问题:设置连接字符串后,无法选择 Entity Framework 6.x,并出现以下错误消息:
An Entity Framework database provider compatible with the latest version of Entity Framework could not be found for your data connection. If you have already installed a compatible provider, ensure you have rebuilt your project before performing this action. Otherwise, exit this wizard, install a comaptible provider, and rebuild your project befre performing this action.
作为最简单的解决方法,我尝试继续使用 EF5,但它在创建数据库模型时抛出异常(在选择要包含在模型中的对象之后,包括一些存储过程)。
采取 2:
如上所述创建项目并安装 NuGet 包。
创建类库项目以促进 Oracle 交互。
在类库项目中安装了与上面相同的 NuGet 包。
向类库项目添加了 ADO.NET 实体数据模型,并向数据库模型添加了一些数据库对象。还向模型中添加了特定连接字符串的自定义构造函数,因为在 Azure Functions 中管理连接字符串是一组单独的令人头疼的问题,我将在稍后处理。
向类库项目添加了一个简单的包装方法,该方法从数据库模型调用存储过程:
public static string NameByEmpNo(int empNo)
{
string result;
MyEntities entities = new MyEntities("metadata=res://*/MyEntities.csdl|res://*/MyEntities.ssdl|res://*/MyEntities.msl;provider=Oracle.ManagedDataAccess.Client;provider connection string='DATA SOURCE=127.0.0.1:1521/ORCL;PASSWORD=tiger;USER ID=SCOTT'");
ObjectParameter name = new ObjectParameter("o_empname", typeof(string));
entities.GET_EMP_NAME_PROC(empNo, name);
result = (string)name.Value;
return result;
}
添加了对 Azure Functions 项目中的类库的引用。
添加了调用 NameByEmpNo 的函数:
[FunctionName("GetNameByEmpNo")]
public static async Task<HttpResponseMessage> GetNameByEmpNo([HttpTrigger(AuthorizationLevel.Function, "get", Route = null)]HttpRequestMessage req, TraceWriter log)
{
int empNo = Int32.Parse(req.GetQueryNameValuePairs()
.FirstOrDefault(q => string.Compare(q.Key, "empno", true) == 0)
.Value);
string empName = ScottAccess.NameByEmpNo(empNo);
return req.CreateResponse(HttpStatusCode.OK, "Employee name: " + empName);
}
问题:在运行时,调用函数失败并出现此错误 消息:
Exception while executing function: GetNameByEmpNo -> The ADO.NET provider with invariant name 'Oracle.ManagedDataAccess.Client' is either not registered in the machine or application config file, or could not be loaded. See the inner exception for details. -> Unable to find the requested .Net Framework Data Provider. It may not be installed.
额外信息:通过控制台应用程序调用时,我的类库可以完美运行。此外,当调用不使用我的类库的函数时,我的 Azure Functions 应用程序可以完美运行...
我被难住了。有没有人有让这种技术组合协同工作的经验,并且可以提供一些关于我出错的地方的见解/提供使基本连接正常工作的步骤?
最佳答案
Azure Functions 中的 Entity Framework 默认提供程序为 System.Data.SqlClient,因此 SQL 连接无需任何配置更改即可工作,但这意味着您必须对 Oracle 连接执行一些特殊操作。问题似乎来自于 Oracle.ManagedDataAccess.Client 库假定在项目的 App.Config 或 Web.Config 文件中可用的配置值,每当您安装 Oracle.ManagedDataAcess.EntityFramework Nuget 包时都会插入这些值。 Azure Functions 没有配置文件,而且我无法找到任何方法在设置 json 文件中指定 Oracle 提供程序。
我在这个post中找到了解决方案
它建议绕过此机制并为 Oracle 创建 DbConfiguration,然后使用 DbConfigurationType 告诉 DbContext 您正在使用哪种配置。
public class OracleDbConfiguration : DbConfiguration
{
public OracleDbConfiguration()
{
SetDefaultConnectionFactory(new OracleConnectionFactory());
SetProviderServices("Oracle.ManagedDataAccess.Client", EFOracleProviderServices.Instance);
SetProviderFactory("Oracle.ManagedDataAccess.Client", new OracleClientFactory());
}
}
[DbConfigurationType(typeof(OracleDbConfiguration))]
public partial class MyEntities : IGISContext
{
//Expose Connection String Constructor
public MyEntities(string connectionString, int commandTimeoutInSeconds = 30) : base(connectionString)
{
this.Database.CommandTimeout = commandTimeoutInSeconds;
}
}
注意:我使用 EF 6 Database First 生成 EDMX;这里的 MyEntities 是一个分部类,用于提供接受连接字符串的构造函数。
oracle 连接将使用指定的 DbConfiguration 类,并且任何 SQL 数据库连接将继续使用默认值。
我的解决方案是使用 Nuget 包:
- EntityFramework 6.2.0
- Oracle.ManagedDataAccess 12.2.1100
- Oracle.ManagedDataAccess.EntityFramework 12.2.1100
关于visual-studio - Azure Functions、 Entity Framework 和 Oracle DB - 基本 POC 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50391453/