【问题标题】:Azure Functions with Entity Framework can't find DbConfiguration in the assembly带有实体框架的 Azure Functions 在程序集中找不到 DbConfiguration
【发布时间】:2016-05-21 19:00:06
【问题描述】:

我正在尝试让 Azure 函数与 EF6 一起使用,但遇到了一些奇怪的零星问题。它已经工作了两次,但其他一百次都没有工作。我得到的错误是:

Microsoft.Azure.WebJobs.Script:出现一个或多个错误。 EntityFramework:设置了“MyDbConfiguration”的实例,但这 未在与“MyDbContext”相同的程序集中发现类型 语境。将 DbConfiguration 类型放在与 DbContext 类型,在 DbContext 上使用 DbConfigurationTypeAttribute type 指定 DbConfiguration 类型,或设置 DbConfiguration 输入配置文件。看 http://go.microsoft.com/fwlink/?LinkId=260883 了解更多信息。

我正在以编程方式设置提供程序,因为我不知道没有app.config 文件的任何其他方法。我之前遇到过 EF 的(可怕的)DbConfiguration 单例限制,但在这种情况下,我不明白为什么它不起作用。

Azure 函数运行时是否将我的 .csx 文件拆分为多个程序集?我尝试将事物更改为嵌套/私有类、内部和各种其他随机更改,但它不起作用(或至少不一致)。我的下一次尝试将正常上传App.config 文件并查看是否可行...

令人不安的是,有时它确实有效。然而,这似乎是随机的,而且很少见。可能在闲置一段时间后;我在写这篇文章时尝试了更多的更改,它最初有效,然后没有,然后在恢复我的更改后仍然没有工作。

我正在通过 Azure 门户的保存和测试按钮对其进行编辑和测试(并首先在 VS 中编写代码以进行语法检查和 IntelliSense...)。以下是代码(后续会更新):

using System.Net;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    log.Info($"C# HTTP trigger function processed a request. RequestUri={req.RequestUri}");

    using (var db = new MyDbContext("...")) {
        log.Info(db.Events.First().id.ToString());
    }
}

#region POCOs
public class Event {
    public long id {get;set;}
    public string data {get;set;}
}
#endregion

[DbConfigurationTypeAttribute(typeof(MyDbConfiguration))]
public class MyDbContext : System.Data.Entity.DbContext {
    public DbSet<Event> Events {get;set;}

    public MyDbContext(string cs) : base(cs) { }
}

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

更新 1: 更糟糕的是,如果我更改类的名称(例如 DbConfigurationx),保存并运行它会出现与上面相同的错误,对于旧的类名,所以我我不确定编辑器中的代码是正在运行的代码……这有点令人担忧。服务应该是这样工作的吗?


更新 2: 添加 App.config 并没有什么不同。坚果。


更新 3: 添加Web.config 似乎可以解决问题——它在六次测试中都有效,但随后又停止工作。我还看到日志消息出现乱序,有时在编译完成之前它正在运行并且测试失败,所以我真的不确定 WTF 是否继续使用此服务,我不确定是否可以推荐在任何地方使用它这不一致。我能够通过避免所有 EF 启动废话并创建自己的数据库连接并将其传递到上下文中来使其工作。如果随着时间的推移这实际上证明是可靠的,我将添加一个答案,说明我是如何做到的。我想手动打开数据库连接是可以的,因为这是一次性请求,不幸的是,我认为这意味着它不使用共享连接池,所以它会减慢一切(目前看来确实如此)。

假设这会奏效,总的来说我很失望; AWS Lambda 是一个更大的 PITA,但它可预测的,后者更为重要。对我来说,完成工作所花费的时间大致相同(处理 EF 和 Azure 的一般怪异,AWS 的控制台配置)。


更新 4: 好吧,我尝试将 POCO 移动到另一个组件中,我计划在我开始工作后进行(尝试成为有效词)。我改为使用 Git 进行部署,以便可以在 VS 中构建。首先,我通过 Git 部署获得了单文件版本,这需要几个小时。构建另一个 DLL 意味着我需要为 JsonIgnore 添加 Newtonsoft.Json (Json) 和 EF。我遇到了 Json 版本问题(DLL 地狱在 .NET 中仍然存在并且运行良好),但这些东西在我能找到的任何地方都没有记录,所以我在我的 project.json 文件中将 Json 作为 nuget 包添加到 EF 旁边,然后它无法更新:

2016-05-22T08:40:36 更新分支“主”。 2016-05-22T08:40:37
无法删除“D:/home/site/wwwroot/execution/bin/common.dll”: 访问被拒绝。

2016-05-22T08:40:39 发生错误,类型:错误,文本: 无法删除“D:/home/site/wwwroot/execution/bin/common.dll”: 访问被拒绝。 ,堆栈跟踪:在 LibGit2Sharp.Core.Ensure.HandleError(Int32 结果) 在 LibGit2Sharp.Core.Proxy.git_checkout_tree(RepositorySafeHandle repo, ObjectId treeId, GitCheckoutOpts& opts) 在 LibGit2Sharp.Repository.CheckoutTree(树树,IList`1 路径, IConvertableToGitCheckoutOpts 选择)在 LibGit2Sharp.Repository.Checkout(树树,CheckoutOptions checkoutOptions,字符串 headTarget,字符串 refLogHeadSpec,签名 签名)在 LibGit2Sharp.Repository.Checkout(分支分支, CheckoutOptions 选项,签名签名)在 LibGit2Sharp.Repository.Checkout(字符串 committishOrBranchSpec, CheckoutOptions 选项,签名签名)在 Kudu.Core.SourceControl.Git.LibGit2SharpRepository.Update(String id)
在 Kudu.Core.Deployment.DeploymentManager.d__25.MoveNext() 2016-05-22T08:40:39 发生错误,类型:错误,文本:一 发生或更多错误。,stackTrace:在 System.Threading.Tasks.Task.ThrowIfExceptional(布尔 includeTaskCanceledExceptions) 在 System.Threading.Tasks.Task.Wait(Int32 毫秒超时, CancellationToken 取消令牌)在 Kudu.Console.Program.PerformDeploy(字符串 appRoot,字符串 wapTargets, 字符串部署程序,字符串 lockPath,IEnvironment env, IDeploymentSettingsManager settingsManager,TraceLevel 级别,ITracer 跟踪器,ITraceFactory traceFactory,IOOperationLock 部署锁), innerText:部署失败,innerStackTrace:在 Kudu.Core.Deployment.DeploymentManager.d__25.MoveNext() 2016-05-22T08:41:25.266 作业主机停止

以为我把它弄坏了,我从project.json 中删除了 Json 包并进行了部署,这似乎可以工作,但现在我在测试时得到了 404。也许我打扰了整个主机......重新启动应用服务似乎可以修复它(一个正在运行的主题),但没有。现在,当我推送到 Git 时,它实际上并没有更新应用程序……“日志流”也没有说什么。叹息。

原来它与上面的“访问被拒绝”错误相同,但该内容不会显示在 Azure Functions 日志流中,但会显示在 /api/logstream 端点中。

我想我现在会[尝试]回到单个文件。


更新 5: 我能够将 EF 位放入 common.csx 文件和 #load 来自我的 run.csx 的文件中。从技术上讲,它可以工作,但是我遇到了另一个问题。虽然我所有的代码都可以正常工作,但没有修改,它是零星的。大多数时候(>75%)我似乎得到了一个“糟糕的部署”,其中我的一些函数无法编译并且不起作用。症状是系统说找不到System.Data.Entity 或者说没有System.Data.SqlClient 提供者。这可以在部署时立即发生,或者在某些请求成功运行后发生。我认为是在一段时间后,比如它空闲了 X 分钟,或者某种内部循环,但我不确定。就好像我在project.json 中指定的EntityFramework 包只是“消失”了。

我可以通过触摸(例如在末尾添加一个空行)project.json 文件(没有 JSON 或 .csx 更改)来“重新部署”,通过 Git 推送,系统会注意到更改,尝试下载包(但不安装任何包),一切都神奇地开始工作。没有代码或包更改!更奇怪的是,有时我的两个函数中的一个会像这样中断,但另一个不会,但它们以相同的方式得到修复。我经常需要重新重新部署才能使我的两个功能都进入工作状态。


由于故障排除,本文可能有些偏离主题。 最初的问题是我的 EF DbContext 没有使用 DbConfiguration 属性以“正常”方式工作,因为根据系统,某处已经存在 DbConfiguration。除非有具体问题可以减少垃圾邮件,否则我将停止更新。

我发现了大约十几个其他问题,从烦恼或意外行为到我必须解决的阻塞问题,但这不是解决这些问题的场所。我很乐意帮助复制或讨论它们,但不幸的是,我不知道那个场地是什么。

【问题讨论】:

标签: c# .net entity-framework azure azure-functions


【解决方案1】:

乔希, 抱歉,您的经历令人沮丧。我目前不在电脑前,但想看看我是否可以提供一些帮助,并会尽快重现您的场景。

  • 构成函数的所有类型(在单个或多个 .csx 文件中)都编译到单个程序集中。所以来自EF的错误确实令人费解。

  • 函数不支持 App.config。

您可以同时尝试的一种方法(直到我们找到导致您遇到的问题的原因)是将您的 EF 类型和 POCO 部署为一个单独的程序集,然后您可以从您的函数中引用该程序集。为此,只需将该程序集复制到函数文件夹下的 bin 文件夹中,并将 #r "YourAssemblyName.dll" 添加到函数文件的顶部。希望这会解除对您的阻止。

当我能够重现您的场景并获得更多信息时,我会发布更新。

【讨论】:

  • 感谢您的回复。如果您能够(即在 MSFT),我可以向您提供有关我的功能的信息以查看它,或者它的 zip 或其他东西。
【解决方案2】:

使用最新版本的实体框架,我已经使用version 6.1.3 进行了测试。然后无需指定任何DbConfiguartion。您可以安全地删除DbConfiguration 代码,只保留DbContext 这不会引发异常,希望一切正常。

using System.Net;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    log.Info($"C# HTTP trigger function processed a request. RequestUri={req.RequestUri}");

    using (var db = new MyDbContext("...")) {
        log.Info(db.Events.First().id.ToString());
    }
}

#region POCOs
public class Event {
    public long id {get;set;}
    public string data {get;set;}
}
#endregion

public partial class MyDbContext : System.Data.Entity.DbContext {

    public MyDbContext(string cs) : base(cs) { }

    public DbSet<Event> Events {get;set;}
}

【讨论】:

    猜你喜欢
    • 2017-04-01
    • 1970-01-01
    • 2016-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-23
    • 1970-01-01
    • 2021-08-31
    相关资源
    最近更新 更多