【问题标题】:querying base and subtype with different include查询具有不同包含的基和子类型
【发布时间】:2021-03-24 20:13:48
【问题描述】:

我有一个类型和子类型

public class Reservation
{
   public int Id {get; set;}
   public TimeSpan Length {get; set;}
}
public class Appointment : Reservation
{
   public Customer Customer {get; set;}
}

数据库上下文

public DbSet<Reservation> Reservations { get; set; }
public DbSet<Appointment> Appointments { get; set; }

每个层次结构表 (TPH) 是当前设置,因为它是 ef core 3.1 的唯一选项。

现在我想查询超集Reservations 并在ReservationAppointment 时包含Customer。我尝试像这样在IQueryable 上使用union

var reservations = context.Appointments.Include(e => e.Customer)
                   .Union(context.Reservations)

但我明白了

InvalidOperationException: '当执行一个集合操作时,两者 操作数必须具有相同的包含操作

虽然可以在内存中执行Union。我想执行一次可以节省一天的行程查询。如果那里只存在解决方案,我可能会迁移到 EntityFramework core 5

编辑:https://github.com/dotnet/efcore/issues/16298

【问题讨论】:

  • 您的表架构是什么样的?继承和关系数据库通常不是很好的匹配。
  • 这是一个表(每个层次结构的表)
  • @Flydog57 你从哪里得到的?继承被大量使用,例如使用微软身份等。EFCore 团队甚至在示例中展示了它。
  • @MHDuke 你期望结果是什么。 Iqueryable&lt;Appointment&gt;Customer 空的 Reservation 类型?还是别的什么?
  • @JHBonarius 不,我希望这两种类型都有。当前仅查询基本类型的保留,将导致一组正确转换的两种类型。那就是说我的实验不彻底。我有更多信息调查并添加问题。 InvalidOperationException:“当前不支持对不同实体类型的设置操作(请参阅#16298)”在我删除 Include() 后

标签: c# entity-framework-core entity-framework-core-3.1


【解决方案1】:

我会建议这种方法,但不确定它是否适用于 EF Core,因为它在 Concat/Union 方面存在问题。你的情况也需要Concat - UNION ALL,而不是Union - UNION

var query1 = 
    context.Appointments.Select(e => new Appointment
    {
        Id = e.Id,
        Length = e.Length,
        Cutomer = e.Customer 
    });

 var query2 = 
    context.Reservations.Select(e => new Appointment
    {
        Id = e.Id,
        Length = e.Length,
     }); 

var query = query1.Concat(query2);

如果您需要具体的类,则必须在客户端进行转换。 ChangeTracker 中也只有记录器的客户。

【讨论】:

  • 您建议在运行时合并结果。这是可行的选择,这就是我在提出问题之前实施它的方式。我更喜欢使用 context.Reservations.AsEnumerable().Union(context.Appointments.Include(e=> e.Customer).AsEnumerable()),因为我的类有私有构造函数并且无法手动设置 id。但这和您的解决方案基本相同。但是,context.Reservations.ToArray() 将检索所有的 Reservations 和 Appointments,因此它是 Union 而不是 Union All。 Include() 语句的问题。
  • AsEnumerable - 正在立即运行查询,所以这不是一个选项。我已经提出了加载客户一对一关系的方法。一对多根本行不通。
  • Enumerable 使用延迟执行策略,所以不,AsEnumerable() 不会立即执行查询,而是在我们枚举结果时执行。另一方面,Select() 确实会立即执行查询。
  • 你是对的,但我的意思是 AsEnumerable 强制执行两个查询。
猜你喜欢
  • 1970-01-01
  • 2012-05-12
  • 1970-01-01
  • 2015-01-10
  • 1970-01-01
  • 2014-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多