问题
In my App, I have some data which are stored on different databases (e.g. identity and User Info are stored separately to Content-related stuff for historical reasons).
However I would like to be able to get advantage of the '.Include' method of EF Core, but as the data is stored in a different DB, is there a way to query two databases in the same DbContext?
回答1:
One option I am seeing is to use views to get all the information from the 2nd database back to the local database.
If using SQL Server as a local database:
1. Create the database link Create linked servers or sp_addlinkedserver
(This step can be skipped if the database is on the same instance)
SQL Server Syntax:
sp_addlinkedserver [ @server= ] 'server' [ , [ @srvproduct= ] 'product_name' ]
[ , [ @provider= ] 'provider_name' ] [ , [ @datasrc= ] 'data_source' ]
[ , [ @location= ] 'location' ] [ , [ @provstr= ] 'provider_string' ]
[ , [ @catalog= ] 'catalog' ]
Example:
EXEC sp_addlinkedserver
@server=N'RemoteServer',
@srvproduct=N'',
@provider=N'SQLNCLI', -- SQL Server Native Client
@datasrc=N'RemoteIp\instance1';
Azure Example:
------ 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;
You can even link to data from Excel files
2. Create a view in the local DB
CREATE VIEW UserObjects AS SELECT Id, UserId, Name, Description FROM RemoteServer.myDatabase.dbo.UserObjects
3. Reference UserObjects as a normal table in the DbContext (views support INSERT/UPDATE/DELETE as long as it is built from a single source table See MS Doc)
public DbSet<User> Users {get;set;}
public DbSet<UserObject> UserObjects {get;set;}
and then use the remote table as a local one:
var user = await _DbContext.Users.Where(u => u.FirstName = "bob").Include(u => u.Objects);
[Warning note] There is no way to have a Primary Key on a view, and therefore to link it as a foreign key constraint. It does not seem possible to add an index to a view either, which could have more or less the same performances gain, but not the constraint part... Reason:
The view must reference only base tables that are in the same database as the view
:( Therefore the following will not work, even if you create the view with the required WITH SCHEMABINDING
:
CREATE UNIQUE INDEX IDX_UserObjects_PK
ON UserObjects (Id);
CREATE INDEX IDX_UserObjects_UserId
ON UserObjects (UserId);
回答2:
If the end goal is to get records from multiple DBs, an alternative way is to call the stored procedure and use DBs in the SP.
Sample to call SP:
_databaseContext.Database.ExecuteSqlCommandAsync($"EXEC {storedProcedureName} @param1, @param2", new SqlParameter("param1", param1), new SqlParameter("param2", param2));
来源:https://stackoverflow.com/questions/49792175/same-dbcontext-several-databases-using-ef-core