如何在Azure函数中指定EntityFramework ProviderName

bec*_*ech 9 configuration entity-framework function azure-functions

我正在尝试将一些webjob代码移植到新的Azure Functions.到目前为止,我已成功导入我的DLL并成功引用它们,但是当我在代码中使用连接字符串时,我收到一条错误消息,说我必须添加ProviderName:

应用程序配置文件中的连接字符串"ConnectionString"不包含必需的providerName属性."

这通常不是问题,因为在webjob(或Web应用程序)中,这将在App或Web.config中,并且连接字符串将被我在Azure中输入的任何内容覆盖.

使用Azure Functions,我没有web.config(虽然我尝试添加一个无效),所以自然缺少providername.

我该如何指定?

编辑: 经过一些游戏和下面的人的一些有用的提示,我几乎设法让它工作.

我现在做的是以下内容:

    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);
Run Code Online (Sandbox Code Playgroud)

这给了我调用数据库所需的内容.我在一个局部类中使用静态方法来获取运行上面代码的数据库实例,然后我用我的MyDB Partial装饰 [DbConfigurationType(typeof(MyDbConfiguration))]

我将该配置定义为:

public class MyDBConfiguration: DbConfiguration
{
    public MyDBConfiguration()
    {
        SetProviderFactory("System.Data.EntityClient", EntityProviderFactory.Instance);
    }
}
Run Code Online (Sandbox Code Playgroud)

当我想要实际使用EF实体时,我的问题仍然存在.在这里,它将尝试使用原始配置初始化数据库类型,再次给我原始错误.根据此堆栈跟踪:

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)
Run Code Online (Sandbox Code Playgroud)

那么我该如何避免这种情况呢?我想我需要一种方法来挂钩所有东西并运行我的自定义setter ..

bec*_*ech 6

最后,斯蒂芬·莱恩德尔把我推向正确的方向; 实体框架的基于代码的配置.

[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)
   {
   }
}
Run Code Online (Sandbox Code Playgroud)

使用像这样的MyDbConfiguration:

public class MyDBConfiguration: DbConfiguration
{
    public MyDBConfiguration()
    {
        SetProviderServices("System.Data.SqlClient", SqlProviderServices.Instance);
        SetDefaultConnectionFactory(new SqlConnectionFactory());
    }
}
Run Code Online (Sandbox Code Playgroud)

使用上面的代码,EF从不要求与AppConfig相关的配置文件.但是请记住,如果你在你的配置文件EF项,它尝试使用它们,所以一定要确保他们走了.

就azure函数而言,这意味着我使用azure中的Azure Functions配置面板来插入没有Metadata和providername的ConnectionString,然后将其加载到GetDB中.

编辑:根据请求,以下是上述的一些解释性文本: 您无法在Azure Functions中添加有关连接的EF元数据,因为它们不使用app.config来指定它.这不是连接字符串的一部分,而是关于连接的元数据,除了EF用于映射到特定C#类和SQL提供程序等的连接字符串之外.为避免这种情况,您可以使用上面的示例对其进行硬编码.您可以通过创建从DBConfiguration继承的类来执行此操作,并使用该标记(使用部分类上的属性)标记EF数据库类.

此DBConfiguration包含一种不同类型的实例化新数据库对象的方法,其中此元数据是硬编码的,但连接字符串是从Azure中的应用程序设置中检索的.在这个例子中我只使用了一个静态方法,但我想它也可能是一个新的构造函数.

一旦有了这个静态方法,就可以使用它来获取数据库代码中的新数据库,如下所示:

using (var db = MyDB.GetDB()) {
   // db code here.
}
Run Code Online (Sandbox Code Playgroud)

这允许您在没有APP.Config的情况下使用EntityFramework,您仍然可以使用Azure Functions APP设置更改连接字符串.

希望有所帮助