与EntityFramework相关的where怎么用?

How to use where in relation with EntityFramework?

我有两个相关的模型。汽车和公告。公告与车哈一对一关系

如何在关系中包含 where?

已更新:属性 的名称是 announcement 而不是 announcements 并且它不是一个集合。

this.context.Cars.Include(a => a.announcement); // stuck here, I want to find the
                                                // announcements that are active. 

注意因为你用了announcements 属性的复数形式,我推断它是一个集合。我的回答是基于这个假设。顺便说一句,规则是对属性使用 PascalCase。

包含始终包含所有相关记录。你必须在之后进行测试:

IEnumerable<Announcement> activeAnnouncements = context.Cars
    .Include(c => c.announcements)
    .SelectMany(c => c.announcements)
    .Where(a => a.IsActive);

请注意,SelectMany 会展平嵌套序列。在这里,它会生成所有汽车中所有公告的序列。

如果您有一对多关系并且需要汽车和活动公告,您可以将两者组合在一个 ValueTuple:

IEnumerable<(Car c, Announcement a)> carsAndActiveAnnouncements = context.Cars
    .Include(c => c.announcements)
    .SelectMany(c => c.announcements, (c, a) => (c, a)) // 1st (c, a) are lambda parameters,
                                                        // 2nd creates tuple.
    .Where(ca => ca.a.IsActive);

获取所有具有活跃公告的汽车,但包括所有公告(在一对一关系中,这始终是单个活跃公告):

IEnumerable<Car> carsHavingActiveAnnouncements = context.Cars
    .Include(c => c.announcements)
    .Where(c => c.announcements.Any(a => a.IsActive));

最后,您可以将此 属性 添加到 Car class(表达式主体语法):

public IEnumerable<Announcement> ActiveAnnouncements =>
    announcements.Where(a => a.IsActive);

与(完整语法)相同:

public IEnumerable<Announcement> ActiveAnnouncements
{
    get {
        return announcements.Where(a => a.IsActive);
    }
}

让您随时轻松检索活动公告。即使在编辑后结果也是准确的。

但是,在这种情况下,您拥有一对一的关系,这并没有多大帮助。


更新: 因为,根据你的更新,announcement 不是一个集合,并且你想要 select 汽车有一个活跃的公告,这是我的新解决方案:

IEnumerable<Car> carsHavingAnActiveAnnouncement = context.Cars
    .Include(c => c.announcement)
    .Where(c => c.announcement.IsActive);

请注意,Where 子句不需要 Include,因为它将被转换为 SQL,并且不依赖于对象引用。但是当然是合法的,如果你想加载公告。

Where() 上车:

this.context.Cars.Include(c => c.announcements).Where(c => c.Value == value);

请注意,我已将您的 'a' 更改为 Include() 中的 'c',因为它代表汽车,而不是公告。

对于 Where() 公告:

this.context.Cars.Where(c => c.announcements.Value == value);

请注意,无需 Include() 公告即可在 Where() 中查看。如果您要在执行查询后读取程序中的公告数据,则只需要 Include()

您在评论中详细说明了查询的目的:

My original problem is only select the cars that have an active annoucement. In another worlds only car data is needed.

如果不需要加载公告数据,则不需要使用Include

我怀疑这可能是 EF/LINQ 和 SQL 之间的混淆。在SQL中,你必须加入你的数据(="include"它在数据集中)才能使用它,不管你是否打算在SELECT,WHERE中使用它,或其他。
但是对于 EF/LINQ,您只需要在非常特定的情况下使用 Include:当您想要将此数据加载到结果集中时,以及当您还没有使用 Select() 时到 return 自定义类型(因为这无论如何都会覆盖包含行为)。

您想要的是过滤数据,而不需要您包含它。您可以简单地调用 Where() 来适当地过滤数据:

var carsWithAnActiveAnnouncement = db.Cars
                                     .Where(c => c.announcement.IsActive)
                                     .ToList();

注意:为了举例,我假设 属性 被称为 IsActive。如果需要,您可以更正此问题。

这会为您提供正确的过滤后的汽车列表,而无需实际加载公告数据,因为您说过不需要它。