如何在 Azure 函数中指定 EntityFramework ProviderName

How to specify EntityFramework ProviderName in an Azure Function

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

The connection string 'ConnectionString' in the application's configuration file does not contain the required providerName attribute."

这通常不是问题,因为在网络作业(或网络应用程序)中,这将在应用程序或 Web.config 中,并且连接字符串将被我在 Azure 中输入的内容简单地覆盖。

使用 Azure Functions,我没有 web.config(虽然我尝试添加一个但没有用),所以自然缺少提供者名称。

如何指定?

编辑: 经过一些尝试和下面的人提供的一些有用的提示后,我几乎设法让它工作了。

我现在做的是:

    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);

这给了我调用数据库所需的东西。我在部分 class 中使用静态方法来获取上面代码 运行 的数据库实例,并用 [DbConfigurationType(typeof(MyDbConfiguration))]

装饰我的 MyDB 部分

我将该配置定义为:

public class MyDBConfiguration: DbConfiguration
{
    public MyDBConfiguration()
    {
        SetProviderFactory("System.Data.EntityClient", EntityProviderFactory.Instance);
    }
}

当我想实际使用 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)

那么 我该如何避免这种情况? 我想我需要一种方法来连接所有内容和 运行 我的自定义 setter..

您可以访问该网站的应用程序设置,方法是转到门户,依次单击 Function app settingsConfigure app settings。这将打开一个边栏选项卡,您可以在其中为您的函数应用设置所有应用设置。只需使用与 web.config.

相同的键和值

Using this question you can set your default factory before opening the connection by having your personal DbConfiguration class (see this link also for usage):

public class MyDbConfiguration : DbConfiguration
{
    public MyDbConfiguration()
    {
        SetDefaultConnectionFactory(new SqlConnectionFactory());
    }
}

现在您需要告诉您的 DbContext 使用新配置。由于无法使用 web.config 或 app.config,您可以使用属性来添加配置:

[DbConfigurationType(typeof(MyDbConfiguration))] 
public class MyContextContext : DbContext 
{ 
}

现在在 DbContext 上使用连接字符串将默认使用 SQL 提供程序。

最后,Stephen Reindel 将我推向了正确的方向; 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:

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

使用上面的代码,EF 从不请求与 AppConfig 相关的配置文件。但记住,如果您的配置文件中有 EF 条目,它 尝试使用它们,因此请确保它们已消失。

就 azure 函数而言,这意味着我使用 azure 中的 Azure Functions 配置面板输入没有元数据和提供者名称的 ConnectionString,然后将其加载到 GetDB 中。

编辑:根据要求,这里是上面的一些解释性文字: 您无法在 Azure Functions 中添加有关连接的 EF 元数据,因为它们不使用 app.config 来指定它。这不是连接字符串的一部分,而是关于连接的元数据,除了 EF 用来映射到特定 C# Class 和 SQL 提供程序等的连接字符串之外。为避免这种情况,您对其进行硬编码使用上面的例子。您可以通过创建一个继承自 DBConfiguration 的 class 来做到这一点,然后用它标记(使用部分 class 上的属性)您的 EF 数据库 class。

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

使用此静态方法后,您可以使用它在数据库代码中获取新数据库,如下所示:

using (var db = MyDB.GetDB()) {
   // db code here.
}

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

希望对您有所帮助

如果您不能简单地更改实例化您的方式,请添加一个答案DbContext。如果您正在调用使用无参数构造函数实例化 DbContext 的代码,就会发生这种情况。

它涉及使用静态构造函数从 Azure 门户的应用程序设置中读取连接字符串,并将其传递给 DbContext 基础构造函数。这使您无需 providerName 并且还允许您保留对门户配置的使用而无需对任何内容进行硬编码。

请参考我接受的答案:

提供的答案是完美的,它对我有很大帮助,但它不是动态的,因为我不想硬编码我的连接字符串。如果您正在使用 azure 函数中的插槽。我一直在寻找一种可以使用多个连接字符串的解决方案。这是我的替代方法,适用于其他正在努力解决此问题的人。

  1. 最重要的是我们了解local.settings.json文件 不适合 AZURE。它是 运行 您在本地的应用程序的名称 明明说所以解决方案与这个文件无关。

  2. App.Config 或 Web.Config 不适用于 Azure 函数连接字符串。如果您有数据库层库,则无法像在 Asp.Net 应用程序中那样使用其中任何一个覆盖连接字符串。

  3. 为了使用,您需要在 Azure 函数的 Application Settings 下的 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

  1. 设置完成后,您需要在应用程序中读取 url 并提供 DBContext。 DbContext 实现了一个带有连接字符串参数的构造函数。默认情况下,构造函数没有任何参数,但您可以扩展它。如果你使用的是 POCO class,你可以简单地修改 DbContext class。如果你像我一样使用数据库生成的 Edmx classes,你不想触摸自动生成的 edmx class 而不是你想在同一个命名空间中创建部分 class 并扩展这个 class 如下。

这是自动生成的 DbContext

namespace myApp.Data.Models
{   

    public partial class myDBEntities : DbContext
    {
        public myDBEntities()
           : base("name=myDBEntities")
        {
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            throw new UnintentionalCodeFirstException();
        }

}

这是新的部分class,您创建

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());
            }
        }
    }
  1. 毕竟你可以从 Azure 设置中获取连接字符串,在你的 Azure Function 项目中使用下面的代码并提供给你的 DbContext myDBEntities 是您在 Azure 门户中为连接字符串提供的名称。
var connString = ConfigurationManager.ConnectionStrings["myDBEntities"].ConnectionString;


 using (var dbContext = new myDBEntities(connString))
{
        //TODO:
}

偶然发现并在 Azure Function 中这样解决了。

public static class MyFunction
{
     // Putting this in more than one place in your project will cause an exception,
     // if doing it after the DbConfiguration has been loaded.
     static MyFunction() =>
         DbConfiguration.Loaded += (_, d) =>
             d.AddDefaultResolver(new global::MySql.Data.Entity.MySqlDependencyResolver());


    // The rest of your function...
    //[FunctionName("MyFunction")]
    //public static async Task Run() {}
}