相同的 DbContext,多个使用 EF Core 的数据库

Same DbContext, Several databases using EF Core

在我的应用程序中,我有一些数据存储在不同的数据库中(例如,由于历史原因,身份和用户信息分别存储在与内容相关的内容中)。

但是我希望能够利用 EF Core 的“.Include”方法,但是由于数据存储在不同的数据库中,有没有办法在同一个 DbContext 中查询两个数据库?

我看到的一个选项是使用视图将所有信息从第二个数据库返回到本地数据库。

如果使用 SQL 服务器作为本地数据库:

1.创建数据库linkCreate linked servers or sp_addlinkedserver

(如果数据库在同一个实例上,这一步可以跳过)

SQL 服务器语法:

    sp_addlinkedserver [ @server= ] 'server' [ , [ @srvproduct= ] 'product_name' ]   
       [ , [ @provider= ] 'provider_name' ] [ , [ @datasrc= ] 'data_source' ]   
       [ , [ @location= ] 'location' ] [ , [ @provstr= ] 'provider_string' ]   
       [ , [ @catalog= ] 'catalog' ]   

示例:

EXEC sp_addlinkedserver     
   @server=N'RemoteServer',   
   @srvproduct=N'',  
   @provider=N'SQLNCLI',   -- SQL Server Native Client
   @datasrc=N'RemoteIp\instance1';  

Azure 示例:

------ Configure the linked server
-- Add one Windows Azure SQL DB as Linked Server
EXEC sp_addlinkedserver
  @server='RemoteServer', -- here you can specify the name of the linked server
  @srvproduct='',       
  @provider='sqlncli', -- using SQL Server Native Client
  @datasrc = 'myServer.database.windows.net',   -- add here your server name
  @location = '',
  @provstr = '',
  @catalog = 'myDatabase'-- add here your database name as initial catalog(you cannot connect to the master database)

-- Add credentials and options to this linked server
EXEC sp_addlinkedsrvlogin
    @rmtsrvname = 'RemoteServer',
    @useself = 'false',
    @rmtuser = 'myLogin',             -- add here your login on Azure DB
    @rmtpassword = 'myPassword'-- add here your password on Azure DB
EXEC sp_serveroption 'RemoteServer', 'rpc out', true;  

您甚至可以 link 从 Excel 个文件中获取数据

2。在本地DB中创建视图

CREATE VIEW UserObjects AS SELECT Id, UserId, Name, Description FROM RemoteServer.myDatabase.dbo.UserObjects

3。在 DbContext 中将 UserObjects 作为正常 table 引用(视图支持 INSERT/UPDATE/DELETE 只要它是从单一来源构建的 table See MS Doc

public DbSet<User> Users {get;set;}
public DbSet<UserObject> UserObjects {get;set;}

然后使用远程 table 作为本地:

var user  = await _DbContext.Users.Where(u => u.FirstName = "bob").Include(u => u.Objects);

[警告说明] 无法在视图上拥有主键,因此 link 将其作为外键约束。 add an index to a view 似乎也不可能,这可能或多或少地获得相同的性能增益,但约束部分不是......原因:

The view must reference only base tables that are in the same database as the view

:( 因此,即使您使用所需的 WITH SCHEMABINDING 创建视图,以下内容 也不会 工作:

CREATE UNIQUE INDEX IDX_UserObjects_PK
    ON UserObjects (Id);  
CREATE INDEX IDX_UserObjects_UserId  
    ON UserObjects (UserId);  

如果最终目标是从多个数据库中获取记录,另一种方法是调用存储过程并在 SP 中使用数据库。

调用 SP 的示例:

_databaseContext.Database.ExecuteSqlCommandAsync($"EXEC {storedProcedureName} @param1, @param2", new SqlParameter("param1", param1), new SqlParameter("param2", param2));