Without seeing your models and query, it is hard to provide an accurate answer. However, the best start is within the database (I would assume SQL Server 2012+).
From your description, the generated query should look, in a very simplified way, like the following:
SELECT A.*, B.Col1, B.Col2, B.Col3
FROM Db1.dbo.TableA AS A
JOIN Db2.dbo.TableB AS B ON B.Id = A.FkToBId
According to this question and its accepted answer, there is no big difference between selecting from the same database vs. selecting from another database within the same instance.
If TableB is big, you should avoid table scans, so the following index should be a good start:
CREATE INDEX IDX_TableB_Id ON TableB (Id) INCLUDE (Col1, Col2, Col3)
However, if the schema is properly normalized, the lookup key should also be a primary key and this index should not be required. I think that if it is clustered, it might bring extra benefit.
Of course, there is a chance that your LINQ generates a slightly different query. If this is the case, edit your question and include table schema, LINQ and generated query.
[EDIT]
Using SqlQuery is an option, but I am thinking about another way:
1) Generate a database context for each database. Lets call them DbContextA and DbContextB
2) Get only required information from TableB, store it in a dictionary for fast lookups and use in an aggregated query.
var ids = DbContextA.TableA.AsNoTracking().Select(item => item.FkToBId).ToList();
var bInfo = DbContextB.TableB.AsNoTracking()
.Where(item => ids.Contains(item.id))
.ToDictionary(
item => item.Id,
item => new { item.Col1, item.Col2, item.Col3 }
);
var aggrInfo = DbContextA.TableA.AsNoTracking()
.ToList()
.Select(item => new
{
AField = item,
Col1 = bInfo[item.FkToBId],
Col2 = bInfo[item.FkToBId],
Col3 = bInfo[item.FkToBId]
};
If this does not provide the required efficiently, SqlQuery remains the only option, as a database context cannot work with two databases at once (source).