我在获取 DbContext
来从 local.settings.json
正确提取连接字符串时遇到问题
上下文:
- 这是一个 Azure 函数项目
- 主要问题代码位于
System.Data.Entity.Internal.AppConfig
- 虽然我有一个
local.settings.json
文件,但这不是 dotnet core。这是.net 4.6.1
错误消息:
'The connection string 'ShipBob_DevEntities' in the application's configuration file does not contain the required providerName attribute."'
Json 配置:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"AzureWebJobsDashboard": ""
},
"ConnectionStrings": {
"ShipBob_DevEntities": {
"ConnectionString": "metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;provider connection string='data source=***;initial catalog=***;persist security info=True;User Id=***;Password=***;;multipleactiveresultsets=True;application name=EntityFramework'",
"providerName": "System.Data.EntityClient"
}
}
}
测试的配置版本:
- 将提供程序名称移至实际的
ConnectionString
token 值中:发生相同的错误 - 将
ConnectionString
属性内的provider
属性设置为EntityClient
:这没有执行任何操作 将
ShipBob_DevEntities
的字符串值设置为ConnectionString
的值:这会引发新的错误,例如keyword metadata is not supported
我尝试使用 ADO 连接字符串,它会引发
代码优先
异常,当您的连接字符串在数据库优先
方法中不正确时,似乎会发生这种情况。
我冒昧地使用dotPeek反编译了EntityFramework.dll
,并将问题追溯到System.Data.Entity.Internal.LazyInternalConnection。 TryInitializeFromAppConfig
。在此方法中,有一个对 LazyInternalConnection.FindConnectionInConfig 的调用,该调用会生成一个 ConnectionStringSettings
对象,该对象的 ProviderName
值设置为 null。不幸的是,我无法调试它似乎用来生成这个值的 AppConfig.cs
类,所以我陷入了困境。
到目前为止我已经查阅了这两篇文章。其中之一规定将提供商名称作为其自己的 token ;但是,这不起作用。
https://github.com/Azure/azure-functions-cli/issues/193
https://github.com/Azure/azure-functions-cli/issues/46
有人知道在 local.settings.json 中用于 Entity Framework 连接的正确格式吗?
最佳答案
我在这里经历了几个类似的问题和答案。他们中的许多人要么具有误导性,要么假设每个人都处于同一水平并了解 azure 功能的工作原理。对于像我这样的新手来说没有答案。我想在这里逐步总结我的解决方案。我不认为提供的答案是最好的选择,因为它迫使您更改自动生成的 edmx 文件,这些文件可能会被错误或下次更新数据库中的 edmx 覆盖。在我看来,这里最好的选择是使用连接字符串而不是应用程序设置。
最重要的是我们了解 local.settings.json 文件 不适用于 azure 。就是在本地运行你的应用程序,就像名字一样 明确地说。所以解决方案与此文件无关。
App.Config 或 Web.Config 不适用于 Azure 函数连接字符串。如果您有数据库层库,则无法像在 Asp.Net 应用程序中那样使用其中任何一个来覆盖连接字符串。
为了使用,您需要在 Azure 函数的
应用程序设置
下的 Azure 门户上定义连接字符串。有 连接字符串。您应该在那里复制 DBContext 的连接字符串。如果是 edmx,则如下所示。有连接类型,我使用它 SQlAzure 但我使用自定义进行了测试(有人声称仅适用于自定义)两者都适用。
metadata=res:///Models.myDB.csdl|res:///Models.myDB.ssdl|res://*/Models.myDB.msl;provider=System.Data.SqlClient;provider connection string='data source=[yourdbURL];initial catalog=myDB;persist security info=True;user id=xxxx;password=xxx;MultipleActiveResultSets=True;App=EntityFramework
- 设置完毕后,您需要读取应用程序中的 URL 并提供 DBContext。 DbContext 实现带有连接字符串参数的构造函数。默认情况下,构造函数没有任何参数,但您可以扩展它。如果您使用 POCO 类,您可以简单地修改 DbContext 类。如果您像我一样使用数据库生成的 Edmx 类,您不想接触自动生成的 edmx 类,而是想在同一命名空间中创建部分类并扩展此类,如下所示。
这是自动生成的 DbContext
namespace myApp.Data.Models
{
public partial class myDBEntities : DbContext
{
public myDBEntities()
: base("name=myDBEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
}
这是您创建的新分部类
namespace myApp.Data.Models
{
[DbConfigurationType(typeof(myDBContextConfig))]
partial class myDBEntities
{
public myDBEntities(string connectionString) : base(connectionString)
{
}
}
public class myDBContextConfig : DbConfiguration
{
public myDBContextConfig()
{
SetProviderServices("System.Data.EntityClient",
SqlProviderServices.Instance);
SetDefaultConnectionFactory(new SqlConnectionFactory());
}
}
}
- 毕竟,您可以使用以下代码从 Azure 设置中的 Azure Function 项目中获取连接字符串,并将其提供给您的 DbContext myDBEntities 是您在 Azure 门户中为连接字符串指定的名称。
var connString = ConfigurationManager.ConnectionStrings["myDBEntities"].ConnectionString; using (var dbContext = new myDBEntities(connString)) { //TODO: }
关于c# - 调试 AzureFunction 以及部署 azure 函数时缺少 ProviderName,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46698103/