我在基本的概念验证工作中遇到了很多麻烦,我通过Azure功能通过实体框架(6.2)访问Oracle DB(11g)。
先决条件: ODT已安装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包时,会在Dependencies - >下添加包。 NuGet,而不是参考文献。
将ADO.NET实体数据模型添加到项目中。
问题:设置我的连接字符串后,选择Entity Framework 6.x不可用,并显示以下错误消息:
与最新版本兼容的实体框架数据库提供程序 找不到您的数据的Entity Framework版本 连接。如果您已经安装了兼容的提供商, 确保在执行此操作之前重建了项目。 否则,退出此向导,安装comaptible提供程序,然后 重建您的项目,请执行此操作。
作为最简单的解决方法,我试图继续使用EF5,但是在创建数据库模型时会抛出异常(在选择要包含在模型中的对象之后,包括一些存储过程)。
选2:
按上述方式创建项目并安装了NuGet包。
创建类库项目以促进Oracle交互。
在类库项目中安装了与上面相同的NuGet包。
将ADO.NET实体数据模型添加到类库项目中,并将一些数据库对象添加到数据库模型中。还为特定连接字符串的模型添加了自定义构造函数,因为管理Azure函数中的连接字符串是一个单独的令人头疼的问题,我稍后会处理。
为类库项目添加了一个简单的包装器方法,该方法从数据库模型中调用存储过程:
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);
}
问题:在运行时,调用该函数失败并显示此错误 消息:
执行函数时出现异常:GetNameByEmpNo - &gt; ADO.NET 具有不变名称的提供者&#39; Oracle.ManagedDataAccess.Client&#39;是 要么未在机器或应用程序配置文件中注册,要么 无法加载。有关详细信息,请参阅内部异常 - &GT;无法 找到请求的.Net Framework数据提供程序。它可能不是 安装。
奖励信息:通过控制台应用程序调用时,我的类库完美运行。此外,我的Azure Functions应用程序在调用不使用我的类库的函数时非常有效...
我很难过。有没有人有经验让这些技术组合在一起工作,可以提供一些洞察我出错的地方/提供基本连接工作的步骤?
答案 0 :(得分:2)
Azure Functions中的实体框架将提供程序默认为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软件包: