0

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

Microsoft.Azure.WebJobs.Script:出现一个或多个错误。EntityFramework:设置了“MyDbConfiguration”实例,但未在与“MyDbContext”上下文相同的程序集中发现此类型。要么将 DbConfiguration 类型放在与 DbContext 类型相同的程序集中,使用 DbContext 类型上的 DbConfigurationTypeAttribute 来指定 DbConfiguration 类型,要么在配置文件中设置 DbConfiguration 类型。有关详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=260883

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

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

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


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

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”:访问被拒绝。, stackTrace: 在 LibGit2Sharp.Core.Proxy.git_checkout_tree(RepositorySafeHandle repo, ObjectId treeId, GitCheckoutOpts& opts) 在 LibGit2Sharp.Core.Ensure.HandleError(Int32 结果) 在 LibGit2Sharp.Repository.CheckoutTree(Tree tree, IList`1 paths, IConvertableToGitCheckoutOpts opts ) 在 LibGit2Sharp.Repository.Checkout(Branch branch, CheckoutOptions options, Signature signature) at LibGit2Sharp.Repository.Checkout(Tree tree, CheckoutOptions checkoutOptions, String headTarget, String refLogHeadSpec, Signature signature) at LibGit2Sharp.Repository.Checkout(String committishOrBranchSpec, CheckoutOptions选项,签名签名)在 Kudu。
在 Kudu.Core.Deployment.DeploymentManager.d__25.MoveNext() 2016-05-22T08:40:39 发生错误,类型:错误,文本:发生一个或多个错误。,stackTrace:在 System.Threading.Tasks.Task。 ThrowIfExceptional(Boolean includeTaskCanceledExceptions) at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancelToken) at Kudu.Console.Program.PerformDeploy(String appRoot, String wapTargets, String deployer, String lockPath, IEnvironment env, IDeploymentSettingsManager settingsManager, TraceLevel级别,ITracer 跟踪器,ITraceFactory traceFactory,IOperationLock deploymentLock),innerText:部署失败,innerStackTrace:在 Kudu.Core.Deployment.DeploymentManager.d__25.MoveNext() 2016-05-22T08:41:25.266 作业主机停止

考虑到我破坏了它,我从中删除了 Json 包project.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 推送,系统注意到更改,尝试下载包(但不安装任何包)来“重新部署” ,一切都神奇地开始工作。没有代码或包更改!更奇怪的是,有时我的两个功能中的一个会像这样中断,但另一个不会,但它们会以同样的方式得到修复。我经常需要重新重新部署才能使我的两个功能都进入工作状态。


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

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

4

2 回答 2

1

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

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

  • 函数不支持 App.config。

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

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

于 2016-05-21T22:09:56.780 回答
0

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

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;}
}
于 2016-11-23T07:26:31.210 回答