entity-framework - 在 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 服务的位置。
感谢您阅读到这里!
解决方案
部署服务时,.config 文件应改为 servicename.exe.config。它应该位于使用 installutil 注册服务的同一文件夹中。请参阅Windows 服务 app.config 位置。
推荐阅读
- python - 如何检查两个数据框(熊猫)中多列中的列值?
- gnuradio - AttributeError: 'rational_resampler_ccc' 对象没有属性 'connect' GNUradio
- php - 为什么 Codeignitor 在验证路由时不接受自动加载控制器类?
- javascript - 无法理解 javascript 中的 indexOf 以便在字符串中找到唯一值?
- java - 如何将 java 类名作为参数传递并将其用作方法中的强制转换
- git - git:将本地分支合并到不同的上游/主分支
- android - NetworkStats.Bucket (querySummaryForDevice) Android 中的空桶
- data-structures - 在最短路径变化的图形的情况下是真的吗?
- caching - 虚拟地址和物理地址有哪些字段?
- mongoose - 如何使用 graphql 对 mongoose 查询进行验证