Linq 多对多包括

Linq many to many include

我有 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");

我总是收到相同的消息:

The Include path expression must refer to a navigation property defined on the type. Use dotted paths for reference navigation properties and the Select operator for collection navigation properties.

我想了解错误信息。

我的问题:

Is "public virtual ICollection ABs" a navigation property ?
What's the difference between "reference navigation properties" and "collection navigation properties" ?

是的。导航 属性 是一种 属性,您可以通过它 "navigate" 从一个实体到另一个实体。它们有两种口味。 A.ABs 是一个 collection 导航 属性, AB.B 是一个 reference 导航 属性。其他属性,如 A.Name,称为 标量属性

What are dotted paths ?

路径中有一个点。但这里的信息并不是很清楚。它适用于嵌套在其他导航属性中的包含属性。

因此 collection 导航属性包含在 Select:

DbContext.Set<A>().Include(a => a.AB.Select(ab => ab.Cees))

(其中 CeesAB 中的 collection)

参考导航属性包含在点中:

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

(其中 DF 是引用)

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

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

... 包括 Select 的引用。好吧,很难想出清晰的 简短异常消息。

What should I change to get my request to work ?

消息不是很清楚,但更糟糕的是,它也没有说明问题所在。您确实使用在类型!

上定义的导航属性
Include(a => a.ABs.Select(ab => ab.B).Where(b => b.Id == 1))

但您不能在其中包含 Where。这是一个臭名昭著的陷阱。 lambda 语法 建议 可以在 Include 中使用任何 LINQ 方法,但实际上只允许 Select. 附加导航属性.

您想要的是 often-requested 功能:过滤包含。目前,EF 仅支持包含完整的 collection。在 EF 7 中,finally filtered Includes 将被支持。

在那之前,你必须使用work-around,例如this one

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