是否有任何可能的方法连接来自使用2个不同DbContext的2个不同数据库的2个表



因此,我正在尝试运行以下查询:

var qarDevicesAffected = from a in context.Alerts
join d in context.Devices on a.ResourceId equals d.Id
where !d.Inactive && !a.Inactive && a.Name.Equals(alertName)
select new AffectedEntity.Device
{
Id = a.Id,
DeviceId = d.Id,
TenantId = d.TenantId,
OperatorName = context.Operators
.Select(o => new { o.Id, o.Name })
.First(o => o.Id == d.TenantId).Name,
DeviceSerialNumber = d.SerialNumber,
CellModuleId = d.CellModule.Id,
CellModuleSerialNumber = d.CellModule.SerialNumber,
LastCheckIn = d.LastCheckIn,
LastDownload = d.LastDownload,
LastPackageCreation = d.LastPackageCreation,
TailNumber = d.Tail.TailNumber,
TailId = d.Tail.Id,
CreationDate = oldDate == "CheckIn" ? d.LastCheckIn.Value : role == "LastDownload" ? d.LastDownload.Value : d.LastPackageCreation.Value,
IsPinned = parameters.PinnedIds != null && parameters.PinnedIds.Contains(d.TenantId)
};
var avWifiDevicesAffected = from a in context.Alerts
join d in dataSyncDbContext.Device on a.ResourceId equals d.DeviceId
join p in dataSyncDbContext.PostedFile on a.ResourceId equals p.DeviceId
join c in dataSyncDbContext.CheckIn on a.ResourceId equals c.DeviceId
where d.Status != "ACTIVE" && !a.Inactive && a.Name.Equals(alertName)
select new AffectedEntity.Device 
{
Id = a.Id,
DeviceId = d.DeviceId,
TenantId = a.TenantId,
OperatorName = context.Operators
.Select(o => new { o.Id, o.Name })
.First(o => o.Id == a.TenantId).Name,
DeviceSerialNumber = d.SerialNumber,
LastCheckIn = c.UpdatedDate,
LastDownload = p.CreatedDate,
TailId = Guid.Parse(d.TailId)
};
var devicesAffected = qarDevicesAffected.Concat(avWifiDevicesAffected);

我最终得到以下错误:

System.InvalidOperationException:不能在单个查询中使用多个DbContext实例处决确保查询使用单个上下文实例。

很明显,EF Core不支持这一点,那么,有没有办法使用查询来获得相同的结果?(连接来自2个不同dbContext的2个表(

EF Core是一个ORM。它将原始sql和对象映射封装在一个漂亮的接口后面。您可以使用它的Linq to Entities功能来构造一个查询,该查询将被转换为sql。然而,对于两个不同的数据库和数据库上下文,EF core不知道如何将它们组合成一个sql语句。

如果数据库在一台服务器上,则必须手动(sql(联接表,并且可以使用Dapper之类的东西来实现较低级别的ORM。

如果数据库在单独的服务器上,您必须了解EF Core遇到困难的原因,因为没有简单的解决方案。相对简单的解决方案是具有单独的查询并将它们连接到内存中。这可能会对性能产生很大影响,但没有好的替代方案。您可以通过调用.AsEnumerable()从Linq到实体(IQueryable(切换到普通Linq(IEnumerable(。(也有异步选项,但情况更复杂(

在您的情况下,我会将其拆分为几个查询,获取您想要的确切数据。这只是获取大量数据,而不是昂贵的大型联接。即,您首先使用适当的筛选器获取Alerts数据,然后根据匹配的alert.ResourceId在另一个表中获取适当的列。您可以通过将资源放在一个数组中,并使用之类的东西过滤表来实现这一点

.Where(x => resourceIds.Contains(x.DeviceId)

你最终将不得不自己做一些对象映射

最新更新