gpt4 book ai didi

c# - 将 Entity Framework Code First 与动态连接字符串结合使用

转载 作者:搜寻专家 更新时间:2023-10-30 20:26:33 25 4
gpt4 key购买 nike

我正在使用 Entity Framework(最新版本 - 我们所说的 6.0)和最新的 .NET 版本(我们所说的版本 4.5.1)编写应用程序。

我面临的问题是我想使用代码优先的方法,因为我真的很喜欢它,但该应用程序由各种数据库组成。现在,添加迁移和更新数据库不是问题。我知道执行此操作的命令,即使 Entity Framework 需要跟踪多个上下文对象也是如此。

但是,这是我正在处理的具体情况:

  • 我使用包含各种用户的通用“设置”数据库,每个用户都有其特定的设置。每个用户通用的一个设置是数据库连接字符串。

这确实意味着我有一个设置表,其中可以配置 5 个用户,但每个用户确实需要另一个数据库(但每个数据库的数据库结构都是相同的)。即使模型相同,我们也使用不同的数据库有非常具体的原因,但我不会详细说明。

现在,问题在于我需要如何在我的 Visual Studio 项目中定义我的第二个上下文。我知道在我的 DbContext 的构造函数中我可以传递一个连接字符串,所以在运行时完全没有问题,但是当我开发时,我还使用 NuGet 包管理器来管理我的数据库的迁移。

有什么方法可以一次升级所有数据库(或一次升级一个数据库),而是通过获取存储在数据库中的连接字符串(因为这取决于用户)?

亲切的问候

最佳答案

好的,我已经设法自己找到了解决方案,我对此非常满意。

首先,我将布置应用程序的结构。

我确实有一个名为 AppServerSettingsContextDbContext,它在源代码中的定义如下:

/// <summary>
/// Initializes a new instance of the <see cref="AppServerSettingsDataContext"/>.
/// </summary>
public AppServerSettingsDataContext()
: base("AppServerSettingsDataContext")
{ }

此上下文有 2 个不同的实体(一个用于成员,一个用于该特定成员的所有设置)。

为了能够执行迁移,我需要在应用程序配置文件中有一个 ConnectionString,就像我们使用的方式一样。

然后,我有另一个名为 AppServerDataContext 的上下文。这有 2 个构造函数,如下所示:

/// <summary>
/// Initializes a new instance of the <see cref="AppServerDataContext"/>.
/// </summary>
public AppServerDataContext() :
this(ConfigurationManager.ConnectionStrings["AppServer"].ConnectionString)
{ }

/// <summary>
/// Initializes a new instance of the <see cref="AppServerDataContext"/>.
/// </summary>
/// <param name="connectionString">The full connection string which is used to connect to the database.</param>
public AppServerDataContext(string connectionString)
: base(connectionString) { }

您会在代码中看到我可以指定连接字符串或为应用程序配置文件加载连接字符串。

您稍后会明白为什么这很重要。

我有 DbContext 指向配置文件中的连接字符串。这不是必须的,但我习惯于那样工作。因此,只有在调用 add-migration 命令时才会使用该连接字符串。这是因为该命令需要数据库来检查数据库的当前状态并添加正确的迁移。

现在,我在一个包含 2 个上下文文件的项目中工作,因此 NuGet 包管理器控制台需要一种方法来识别它。

因此,可以使用如下命令:

  1. 为特定上下文启用迁移:

    • `PM> 启用迁移 -ContextTypeName: -MigrationsDirectory:

这是一个我需要执行两次的命令,每个上下文一次。

然后,在我的 AppServerSettings 上下文的 Seed 方法中,我将编写以下代码:

/// <summary>
/// Runs after upgrading to the latest migration to allow seed data to be updated.
/// </summary>
/// <param name="context">Context to be used for updating seed data.</param>
protected override void Seed(AppServerSettingsDataContext context)
{
// Creates the Member and assign all the settings which are required for the application to function.
context.Members.AddOrUpdate(x => x.Name, new Member("Povlo")
{
Settings = new List<MemberSettings>
{
new MemberSettings("DatabaseConnectionString", "Removed for Security Reasons"),
}
});

// Make sure that for every member, the database is created by using the "MigrateDatabaseToLatestVersion" migration.
foreach (var setting in context.Members.Select(member => member.Settings.FirstOrDefault(x => x.Key == "DatabaseConnectionString")))
{
using (var appServerContext = new AppServerDataContext(setting.Value))
{
var de = new MigrateDatabaseToLatestVersion<AppServerDataContext, AppServer.Configuration>();
de.InitializeDatabase(appServerContext);

appServerContext.Database.Initialize(true);
}
}
}

我在这里所做的基本上是首先使用给定的连接字符串创建一个成员(可以有多个)。

然后,在相同的方法中,我有一个 foreach 循环,它将根据数据库中的连接字符串创建一个上下文。那么对于这个上下文,数据库正在升级到最新版本。

这样做的好处是我使用了代码优先的方法,所有的数据库都是最新的。

这样做的缺点是所有模型都需要完全相同。

关于c# - 将 Entity Framework Code First 与动态连接字符串结合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30976130/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com