首页 > 解决方案 > .NetCore 3.1 中的 EntityFramework 和多个 DBContext

问题描述

我有一个“工作”的 .NetCore 2.2 应用程序。我的客户要求进行一些修改,我决定尝试将应用程序迁移到 .NetCore 3.1。EntiryFramework 让我很适应。

我的客户有许多 MS SQL “数据库”,例如“人员”、“预订”、“计费”等。我必须创建将人员中的人员与其他人的计费和/或其他记录相匹配的查询是很常见的数据库。我现在在 2.2 中做这种事情。

如果我运行类似于以下内容的查询,则会出现异常:

Cannot use multiple DbContext instances within a single query execution. Ensure the query uses a single context instance.

此查询似乎使用单个上下文,但该devicesInRoom实体隐藏在其中。 devicesInRoom是类型IQueryable<string>并且来自我之前运行的“实用程序”查询。基本上我只想要 与中的项目之一相同的reservations地方。reservations.DevicedevicesInRoom

var reservations = (
    from reservation in reservationsContext.Reservations
    from reservationType in reservationsContext.Types.Where(
        reservationType => reservationType.Id.Equals(reservation.TypeId)
    ).DefaultIfEmpty()
    from roomMates in devicesInRoom
        .Where(
            roomMates => roomMates.Equals(reservation.Device)
        ).DefaultIfEmpty()
    where reservation.StartDate < viewEnd
          && reservation.EndDate > viewStart
          && reservation.Deleted.Equals(false)
    select reservation.Device
).ToList();

如果我将此查询重写为:

var reservations = (
    from reservation in reservationsContext.Reservations
    from reservationType in reservationsContext.Types.Where(
        reservationType => reservationType.Id.Equals(reservation.TypeId)
    ).DefaultIfEmpty()
    where reservation.StartDate < viewEnd
          && reservation.EndDate > viewStart
          && reservation.Deleted.Equals(false)
    select reservation.Device
).ToList();

var thing = (
    from res in reservations
    from roomMates in devicesInRoom
        .Where(
            roomMates => roomMates.Equals(res)
        ).DefaultIfEmpty()
    select res
).ToList();

我仍然收到上面的错误。我不明白为什么查询跨数据库是一件坏事。

我该如何解决?

标签: entity-framework.net-core-3.1

解决方案


我不明白为什么查询跨数据库是一件坏事。

EF 从来不支持它。EF Core 2x 通过简单地评估客户端上的查询“解决”了这个问题和许多其他查询翻译限制。EF 3 删除了这个“功能”,您必须通过从 LINQ-to-Entities 切换到 LINQ-to-Objects 来明确声明何时需要客户端评估,通常是通过引入.ToList().AsEnumerable()从服务器端评估转换到客户端评估。

就像是:

var reservations = (
    from reservation in reservationsContext.Reservations
    from reservationType in reservationsContext.Types.Where(
        reservationType => reservationType.Id.Equals(reservation.TypeId)
    ).DefaultIfEmpty().ToList()
    from roomMates in devicesInRoom.ToList()
        .Where(
            roomMates => roomMates.Equals(reservation.Device)
        ).DefaultIfEmpty()
    where reservation.StartDate < viewEnd
          && reservation.EndDate > viewStart
          && reservation.Deleted.Equals(false)
    select reservation.Device
).ToList();

推荐阅读