问题描述
我正在尝试将一些 webjob 代码移植到新的 Azure Functions.到目前为止,我已经成功地导入了我的 DLL 并成功引用了它们,但是当我在代码中使用连接字符串时,我收到一条错误消息,提示我必须添加 ProviderName:
I'm trying to port some webjob code to the new Azure Functions. So far I've managed to import my DLL's and reference them succesfully, but when I use the connection string in my code, I get an error saying I have to add the ProviderName:
应用程序中的连接字符串ConnectionString"配置文件不包含所需的 providerName属性."
这通常不是问题,因为在 webjob(或 web 应用程序)中,这将在 App 或 Web.config 中,并且连接字符串将简单地被我在 Azure 中输入的任何内容覆盖.
Which is normally not a problem because in a webjob (or web app), this will be in the App or Web.config, and the connectionstring will simply be overwritten with whatever I entered in Azure.
使用 Azure Functions,我没有 web.config(虽然我尝试添加一个但无济于事),所以很自然地缺少 providername.
With Azure Functions, I don't have a web.config (Although I tried adding one to no avail), so naturally the providername is missing.
如何指定?
经过一些尝试和下面的人提供的一些有用的提示,我几乎设法让它工作了.
After some playing around and some helpful tips by people below, I've almost managed to get it working.
我现在要做的是:
var connString = **MY CONN STRING FROM CONFIG**; // Constring without metadata etc.
EntityConnectionStringBuilder b = new EntityConnectionStringBuilder();
b.Metadata = "res://*/Entities.MyDB.csdl|res://*/Entities.MyDB.ssdl|res://*/Entities.MyDB.msl";
b.ProviderConnectionString = connString.ConnectionString;
b.Provider = "System.Data.SqlClient";
return new MyDB(b.ConnectionString);
这给了我调用数据库所需的东西.我在部分类中使用静态方法来获取运行上述代码的数据库实例,并用 [DbConfigurationType(typeof(MyDbConfiguration))]
Which gives me what I need for calling the database. I use a static method in a partial class to get an instance of the Database which runs the above code, and I decorate my MyDB Partial with [DbConfigurationType(typeof(MyDbConfiguration))]
我将该配置定义为:
public class MyDBConfiguration: DbConfiguration
{
public MyDBConfiguration()
{
SetProviderFactory("System.Data.EntityClient", EntityProviderFactory.Instance);
}
}
当我想实际使用 EF 实体时,我的问题仍然存在.在这里,它将尝试使用原始配置初始化数据库类型,再次给我原始错误.根据此堆栈跟踪:
My problem remains when I want to actually use the EF Entities. Here, it will try to initialize the database type using the original configuration, giving me the original error once again. As per this stack trace:
at Void Initialize()
at System.Data.Entity.Internal.EntitySetTypePair GetEntitySetAndBaseTypeForType(System.Type)
at Void InitializeContext()
at System.Data.Entity.Core.Objects.ObjectContext CreateObjectContextFromConnectionModel()
at Void Initialize()
at Boolean TryInitializeFromAppConfig(System.String, System.Data.Entity.Internal.AppConfig)
at Void InitializeFromConnectionStringSetting(System.Configuration.ConnectionStringSettings)
那么我该如何避免这种情况?我想我需要一种方法来挂钩所有内容并运行我的自定义设置器..
So how do I avoid this? I guess I need a way to hook into everything and run my custom setter..
推荐答案
最后,Stephen Reindel 把我推向了正确的方向;实体框架的基于代码的配置.
In the end, Stephen Reindel pushed me in the right direction; Code-based Configuration for Entity Framework.
[DbConfigurationType(typeof(MyDBConfiguration))]
public partial class MyDB
{
public static MyDB GetDB()
{
var connString = **MY CONN STRING FROM SOMEWHERE**; // Constring without metadata etc.
EntityConnectionStringBuilder b = new EntityConnectionStringBuilder();
b.Metadata = "res://*/Entities.MyDB.csdl|res://*/Entities.MyDB.ssdl|res://*/Entities.MyDB.msl";
b.ProviderConnectionString = connString.ConnectionString;
b.Provider = "System.Data.SqlClient";
return new MyDB(b.ConnectionString);
}
public MyDB(string connectionString) : base(connectionString)
{
}
}
像这样使用 MyDbConfiguration:
With MyDbConfiguration like this:
public class MyDBConfiguration: DbConfiguration
{
public MyDBConfiguration()
{
SetProviderServices("System.Data.SqlClient", SqlProviderServices.Instance);
SetDefaultConnectionFactory(new SqlConnectionFactory());
}
}
使用上面的代码,EF 永远不会要求 AppConfig 相关的配置文件.但是记住,如果您的配置文件中有 EF 条目,它会尝试使用它们,因此请确保它们已消失.
With the above code, EF never asks for AppConfig-related config files. But remember, if you have EF entries in your config file, it will attempt to use them, so make sure they're gone.
就 azure 函数而言,这意味着我使用 azure 中的 Azure Functions 配置面板在没有元数据和提供程序名称的情况下插入了我的 ConnectionString,然后将其加载到 GetDB 中.
In terms of azure functions, this means I used the Azure Functions configuration panel in azure to punch in my ConnectionString without the Metadata and providername, and then loaded that in GetDB.
根据要求,这里是上面的一些解释性文字:无法在 Azure Functions 中添加有关连接的 EF 元数据,因为它们不使用 app.config 来指定它.这不是连接字符串的一部分,而是关于连接的元数据,除了 EF 用来映射到特定 C# 类和 SQL 提供程序等的连接字符串.为避免这种情况,您可以使用上面的示例对其进行硬编码.您可以通过创建一个继承自 DBConfiguration 的类来做到这一点,然后用它标记(使用部分类上的属性)您的 EF 数据库类.
As per request, here is some explanatory text of the above:You can't add EF metadata about the connection in Azure Functions, as they do not use an app.config in which to specify it. This is not a part of the connection string, but is metadata about the connection besides the connection string that EF uses to map to a specific C# Class and SQL Provider etc. To avoid this, you hardcode it using the above example. You do that by creating a class inheriting from DBConfiguration, and you mark (with an attribute on a partial class) your EF database class with that.
此 DBConfiguration 包含另一种实例化新数据库对象的方法,其中此元数据是硬编码的,但连接字符串是从 Azure 中的应用设置中检索的.在这个例子中我只是使用了一个静态方法,但我猜它也可能是一个新的构造函数.
This DBConfiguration contains a different kind of way to instantiate a new database object, in which this metadata is hardcoded, but the connectionstring is retrieved from your app settings in Azure. In this example I just used a static method, but I guess it could be a new constructor also.
一旦你有了这个静态方法,你就可以在你的数据库代码中使用它来获取一个新的数据库,就像这样:
Once you have this static method in play, you can use that to get a new database in your database code, like this:
using (var db = MyDB.GetDB()) {
// db code here.
}
这允许您在没有 APP.Config 的情况下使用 EntityFramework,并且您仍然可以使用 Azure Functions APP 设置更改连接字符串.
This allows you to use EntityFramework without an APP.Config, and you can still change the connectionstring using Azure Functions APP settings.
希望有帮助
这篇关于如何在 Azure 函数中指定 EntityFramework ProviderName的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!