与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
。如果需要,您可以更正此问题。
这会为您提供正确的过滤后的汽车列表,而无需实际加载公告数据,因为您说过不需要它。
我有两个相关的模型。汽车和公告。公告与车哈一对一关系
如何在关系中包含 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
。如果需要,您可以更正此问题。
这会为您提供正确的过滤后的汽车列表,而无需实际加载公告数据,因为您说过不需要它。