Linq多对多包含关系

3

我有三个实体

public class A
{ 
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<AB> ABs { get; set; }
}

public class AB
{
    public int AId { get; set; }

    public virtual A A { get; set; }

    public int BId { get; set; }

    public virtual B B { get; set; }
}

public class B
{
    public int Id { get; set; }
    public virtual ICollection<AB> ABs { get; set; }
}

我需要在Linq中编写以下SQL语句:
SELECT * FROM A, AB
WHERE
A.Name = 'name'
AND AB.BId = 1

我已经尝试过:

DbContext.Set<A>().Include(a => a.ABs.Select(ab => ab.B).Where(b => b.Id == 1)).Single(a => a.Name == "name");

DbContext.Set<A>().Include(a => a.ABs.Where(ab => ab.BId == 1)).Single(a => a.Name == "name");

DbContext.Set<A>().Include(a => a.ABs.Select(ab => ab.BId == 1).Single(a => a.Name == "name");

DbContext.Set<A>().Include(a => a.ABs.Any(ab => ab.BId == 1)).Single(a => a.Name == "name");

我总是收到同样的信息:

包含路径表达式必须引用在类型上定义的导航属性。对于参考导航属性,请使用点分路径,对于集合导航属性,请使用Select运算符。

我想理解这个错误消息。
我的问题:
  • "public virtual ICollection ABs" 是导航属性吗?
  • 什么是点分路径?
  • "参考导航属性"和"集合导航属性"之间有什么区别?
  • 我应该改变什么来使我的请求工作?
2个回答

3
“public virtual ICollection ABs”是导航属性吗?“引用导航属性”和“集合导航属性”的区别是什么?
是的。导航属性是指您可以从一个实体“导航”到另一个实体的属性。它们分为两种类型。“A.ABs”是一个集合导航属性,“AB.B”是一个引用导航属性。其他属性,如“A.Name”,称为标量属性
什么是点路径?
带有点的路径。但是这里的信息并不是非常清楚。它适用于嵌套在其他导航属性中的包含属性。
因此,通过Select选择包含集合导航属性:
DbContext.Set<A>().Include(a => a.AB.Select(ab => ab.Cees))

(其中CeesAB中的一个集合)

而引用导航属性则通过点号来包含:

DbContext.Set<A>().Include(a => a.D.F)

(其中DF是引用)

但对我来说这一点都不清楚,因为...

Include(a => a.ABs.Select(ab => ab.B))

...包含一个由Select引用的参考。很难想象出清晰简明的异常消息。

我应该改变什么才能让我的请求工作?

这个消息不太清楚,更糟糕的是它也没有说明问题所在。你确实使用了在类型上定义的导航属性!

Include(a => a.ABs.Select(ab => ab.B).Where(b => b.Id == 1))

但是你不能在其中使用Where,这是一个臭名昭著的陷阱。Lambda语法暗示任何LINQ方法都可以在Include中使用,但实际上只允许使用Select.来追加导航属性。
你需要的是一个经常请求的功能:过滤 Include。目前,EF仅支持包含完整集合。在EF 7中,将终于支持过滤的Include
在那之前,您必须使用解决方法,例如此方法

0
var ww = _context.Agentes.Include(a => a.AgentesObjetos.Select(ab => ab.Objeto)).ToList();

错误 InvalidOperationException: Include 属性的 lambda 表达式a => {from AgenteObjeto ab in a.AgentesObjetos select [ab].Objeto}是无效的。

该表达式应该表示一个属性访问:t => t.MyProperty

要针对派生类型声明的导航,请指定目标类型的显式类型化 lambda 参数,例如 (Derived d) => d.MyProperty

有关此主题的更多信息,包括相关数据,请参见http://go.microsoft.com/fwlink/?LinkID=746393


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接