【问题标题】:EF Core and Multiple DatabasesEF Core 和多个数据库
【发布时间】:2018-09-03 23:52:11
【问题描述】:

我有一个包含三个数据库的旧系统

  1. 供应商
  2. 自定义代码
  3. 日志数据

供应商包含来自我们的供应商应用程序的控制和日志数据。

CustomCode 包含大量视图和存储过程,它们连接到 Vendor 和 LogData

LogData 包含来自我们的 CustomCode 流程的结果。例如:每日/每周/每月摘要和结果。

我正在编写一个可以在地图上绘制数据的网站。单位列表来自 CustomCode 中的视图。 Summary 记录来自 LogData,各个日志点由 CustomCode 中的存储过程从 Vendor 检索。

我从 CustomCode 的 DbContext 开始,但似乎无法导航到第二个 DbContext 中的属性到 LogData

我可以在不同上下文中的对象之间链接导航属性吗?

我可以有一个连接多个数据库的上下文吗?

请注意,这与多租户或多模式无关

【问题讨论】:

  • 我可以在不同上下文中的对象之间链接导航属性,我认为这是不可能的.. 最好创建一个辅助方法或其他东西.. 互连字符串关系是我认为非常危险(没有人可以确保这种关系,但你的代码)..
  • 不,每个上下文代表一个不同的连接,你不能这样做。 EF 不适用于此用例
  • 您必须从每个上下文加载数据,然后加入内存。
  • 如果数据库可以相互通信(即在同一台服务器上),那么创建一个存储过程来执行所需的查询(可以连接来自不同数据库的表)从那里你应该能够执行程序形式EF
  • 两位先生愿意发表一个我可以(遗憾地)接受的答案吗?

标签: c# asp.net-core entity-framework-core


【解决方案1】:

我可以在不同上下文中的对象之间链接导航属性吗?

没有。

我可以在一个上下文中连接多个数据库吗?

没有。

建议:

如果数据库可以相互通信(即在同一台服务器上),这似乎已经完成了

CustomCode 包含大量视图和存储过程,它们连接到 Vendor 和 LogData

然后创建一个存储过程来执行所需的查询(它可以连接来自不同数据库的表)。

您应该能够从那里公开和执行实体框架中的过程以执行所需的功能。

这将避免有多个上下文并尝试将数据连接到内存中,如果数据集很大,这可能会产生不利影响。

【讨论】:

  • 唯一的问题是将 sp 加载到 DbQuery 而不是 DbSet 意味着我不能将它们用作导航属性的权威实体。我可以使用更多的单片 sp,但是嗯。 EF 给了,它带走了 ;)
【解决方案2】:

在 EF Core 5.0 的新功能中,现在可以更轻松地创建 DbContext 实例而无需任何连接或连接字符串。此外,现在可以在上下文实例上更改连接或连接字符串。此功能允许相同的上下文实例动态连接到不同的数据库。

参考:https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-5.0/whatsnew#use-a-c-attribute-to-indicate-that-an-entity-has-no-key

【讨论】:

  • 您应该提供一个示例,说明如何在 EF Core 5.0 中实际执行此操作——我敢打赌,这会给您带来很多选票。
  • @vivek 该参考没有任何关于动态连接到不同数据库的相同 DbContext 实例的内容。它只显示“新功能”,但没有谈论您提到的那个。能否提供示例或示例链接?
【解决方案3】:

不,您不能在不同上下文中的对象之间链接导航属性。一个上下文代表一个特定的连接或数据库。您可以尝试从多个上下文 (DB) 获取数据并将它们连接起来并在内存中使用。

【讨论】:

  • 这给了我这样的想法......好吧,在我的情况下,它们是同一个数据库,所以也许我应该只使用新的身份表来加入我的旧表,即使它们在单独的上下文中作为数据库是数据库优先的,身份的东西是模型优先的..
【解决方案4】:

也在其他地方回答 (https://stackoverflow.com/a/54347237/861352),但要点如下:

这实际上似乎是一个已知问题,正在制定解决方案(尽管尚未确定优先级):

https://github.com/aspnet/EntityFrameworkCore/issues/4019

不过,我确实找到了解决此问题的临时解决方案,它基于两个来源:

https://stackoverflow.com/a/26922902/861352(EF6解决方案) https://weblogs.asp.net/ricardoperes/interception-in-entity-framework-core

这里是:


如何使用一个 EF Core DbContext 进行(同一服务器)跨 DB 联接


您需要安装 Microsoft.Extensions.DiagnosticAdapter Nuget 包

using System;
using System.Data.Common;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.Extensions.DiagnosticAdapter;

namespace Example
{
    public class CommandInterceptor
    {
        [DiagnosticName("Microsoft.EntityFrameworkCore.Database.Command.CommandExecuting")]
        public void OnCommandExecuting(DbCommand command, DbCommandMethod executeMethod, Guid commandId, Guid connectionId, bool async, DateTimeOffset startTime)
        {
            var secondaryDatabaseName = "MyOtherDatabase";
            var schemaName = "dbo";
            var tableName = "Users";

            command.CommandText = command.CommandText.Replace($" [{tableName}]", $" [{schemaName}].[{tableName}]")
                                                     .Replace($" [{schemaName}].[{tableName}]", $" [{secondaryDatabaseName}].[{schemaName}].[{tableName}]");
        }
    }
}

用您的数据库名称、表架构和表名替换“MyOtherDatabase”、“dbo”和“用户”,可能来自配置等。

然后将该拦截器附加到您的上下文中。

using System.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;


var context = new MultipleDatabasesExampleDbContext(optionsBuilder.Options);

// Add interceptor to switch between databases
var listener = context.GetService<DiagnosticSource>();
(listener as DiagnosticListener).SubscribeWithAdapter(new CommandInterceptor());

在我的例子中,我将上面的内容放在 MultipleDatabasesExampleDbContextFactory 方法中。

现在您可以像引用一个数据库一样使用上下文。

context.Customers // Default database defined in connection string
context.Users     // MyOtherDatabase (a different database on the same server)

【讨论】:

  • 我认为这是一个肮脏的解决方案,而且不是很健壮。在一个事务中写入到不同的数据库是一个可能的障碍。一个不太脏(但仍然不可靠)的解决方案是使用同义词。
  • @GertArnold 我并没有说这是一个理想的解决方案,我说这是一个临时解决方案,虽然他们正确地解决了问题,如前所述。上面的解决方案已经使用基本的读取、写入和跨数据库连接进行了测试,并且到目前为止我的使用一直保持不变。如果您使用同义词有更好的解决方案,请发布完整的答案。
  • 如果数据库在不同的服务器上怎么办?
猜你喜欢
  • 2019-08-03
  • 2023-02-23
  • 1970-01-01
  • 1970-01-01
  • 2023-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多