首页 > 解决方案 > 在 ASP.NET Core Windows 服务项目中解析 EFv6.3 中的连接字符串

问题描述

我有一个作为 Windows 服务运行的 ASP.NET Core 应用程序。由于项目要求,我使用的是 Entity Framework v6.3(而不是使用 EF Core)。

在执行迁移以及将服务发布到服务器时,我无法检索正确的连接字符串。在本地运行服务时,成功检索到连接字符串。

据我了解,Entity Framework 6 应该从 web.config 或 app.config 文件中检索连接字符串,对吧?因此,我有一个包含两个连接字符串的 app.config 文件,例如

<connectionStrings>
    <add name="DataContext" providerName="System.Data.SqlClient" connectionString="Server=localhost\SQLEXPRESS;[redacted]" />
    <add name="CrmContext" providerName="System.Data.SqlClient" connectionString="Server=localhost\SQLEXPRESS;[redacted]" />
</connectionStrings>

在我的 Startup 课程中,我已经注册了两个数据库上下文,例如

services.AddTransient<DataContext>();
services.AddTransient<CrmContext>();

在 Razor 页面上,当我在本地计算机上实例化两个数据上下文时,我可以看到正在为两个上下文解析正确的连接字符串(通过使用 _crmContext.Database.Connection.ConnectionString)。

当我尝试在我的 CrmContext 上使用 update-database 命令添加迁移(启用自动迁移)时,未解析正确的连接字符串。相反,它默认使用默认连接字符串创建 LocalDB 数据库: (localdb)\MSSQLLocalDB

为什么它没有使用我在 app.config 文件中提供的连接字符串?我也是一个 web.config 文件,但它也不能从那里解决。

CrmContext.cs

public class CrmContext : DbContext
{
    public CrmContext() : base("CrmContext")
    {
        Database.SetInitializer<CrmContext>(null);
    }

    public IDbSet<CustomerDetails> CustomerDetails { get; set; }
}

CrmConfiguration.cs

internal sealed class CrmConfiguration : DbMigrationsConfiguration<CrmContext>
{
    public CrmConfiguration()
    {
        AutomaticMigrationsEnabled = true;
    }

    protected override void Seed(CrmContext context)
    {
        ...

        context.SaveChanges();
    }
}

我尝试通过指定我的 CrmConfiguration 文件来显式更新 CRM 连接:

update-database -ConfigurationTypeName CrmContext

当我这样做时,它会创建并更新 LocalDB 数据库,而不是使用我的连接字符串。

我还尝试显式引用连接字符串:

update-database -ConnectionStringName "CrmContext"

这会导致此错误:

在应用程序配置文件中找不到名为“CrmContext”的连接字符串。

我的 CrmContext 类存在于我的 ASP.NET Core Windows 应用程序中,而我的 DataContext 类存在于一个单独的“数据”项目中(因为它与 ASP.NET MVC v5 应用程序共享)

在此处输入图像描述

在此处输入图像描述

当我发布我的服务并将应用程序安装为 Windows 服务时,我发现它根本不会从任何配置文件中获取连接字符串 - 它再次只是查找默认的 localdb 数据库。据我了解,它应该从我的 PaymentBatchProcessorService.exe.config 文件中获取它,对吗?

我的 PaymentBatchProcessorService.exe.config 文件如下所示:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <connectionStrings>
    <add name="DataContext" providerName="System.Data.SqlClient" connectionString="redacted" />
    <add name="CrmContext" providerName="System.Data.SqlClient" connectionString="redacted" />
  </connectionStrings>
</configuration>

在此处输入图像描述

根据Microsoft 文档,应该可以通过 Program.cs 文件中的以下代码加载其他 XML 配置文件,但 EntityFramework 仍然没有获取连接字符串:

Host.CreateDefaultBuilder(args)
    .UseWindowsService()
    .ConfigureAppConfiguration((hostingContext, config) =>
    {
        var workingDirectoryPath = Environment.GetEnvironmentVariable(EnvironmentVariables.ServiceWorkingDirectory);

        config.AddXmlFile(Path.Combine(workingDirectoryPath, "app.config"));
        config.AddXmlFile(Path.Combine(workingDirectoryPath, "web.config"));
    })

例如,在上面的示例中,工作目录路径解析为我的 .exe 用于 Windows 服务的位置。

感谢您阅读到这里!

标签: entity-frameworkasp.net-coreentity-framework-6

解决方案


部署服务时,.config 文件应改为 servicename.exe.config。它应该位于使用 installutil 注册服务的同一文件夹中。请参阅Windows 服务 app.config 位置


推荐阅读