Entity Framework 在 "over apply" 之后失去对导航属性的跟踪
Entity Framework loses track of navigation properties after "over apply"
我有一个像 Person 这样的模型,它可以住在 Street 和 Street位于城市,而城市则位于国家。还有一些 ActivityRecords 用于一些 Persons.
public class Country
{
[Key]
public int id { get; set; }
public string name { get; set; }
}
public class City
{
[Key]
public int id { get; set; }
public string name { get; set; }
[ForeignKey("Country")]
public int country_id { get; set; }
public virtual Country Country { get; set; }
}
public class Street
{
[Key]
public int id { get; set; }
public string name { get; set; }
[ForeignKey("City")]
public int city_id { get; set; }
public virtual City City { get; set; }
}
public class Person
{
[Key]
public int id { get; set; }
ForeignKey("Street")]
public int? street_id { get; set; }
public virtual Street Street { get; set; }
//no connection to ActivityRecord[]
}
public class ActivityRecord
{
[Key]
public int id { get; set; }
public string desc { get; set; }
[ForeignKey("Person")]
public int? person_id { get; set; }
public virtual Person Person { get; set; }
}
我需要列出一部分人员信息,包括他们在国家/地区的地址以及其中一项活动(如果有的话)(否则为空)。我故意删除了所有细节和列以简化示例。
所以,我在我的代码中做到了这一点:
context.Persons.AsNoTracking().OrderBy(p => p.id).Skip(0).Take(10).GroupJoin(
context.ActivityRecords,
p => p.id,
ar => ar.person_id,
(p, ar) => new { p = p, ar = ar.FirstOrDefault() } //join 1 or 0 entries
).Select(result => new
{
id = result.t.id,
street = result.t.Street.name,
city = result.t.Street.City.name,
country = result.t.Street.City.Country.name
}).ToArray();
当我检查 EF 生成的查询时,我多次看到相同 table 上的左外连接(街道、城市):
SELECT
[Limit1].[id] AS [id],
[Extent3].[name] AS [name],
[Extent5].[name] AS [name1],
[Extent8].[name] AS [name2]
FROM (SELECT TOP (10) [Extent1].[id] AS [id], [Extent1].[street_id] AS [street_id]
FROM ( SELECT [Extent1].[id] AS [id], [Extent1].[street_id] AS [street_id], row_number() OVER (ORDER BY [Extent1].[id] ASC) AS [row_number]
FROM [dbo].[Persons] AS [Extent1]
) AS [Extent1]
WHERE [Extent1].[row_number] > 0
ORDER BY [Extent1].[id] ASC ) AS [Limit1]
OUTER APPLY (SELECT TOP (1) [Extent2].[id] AS [id]
FROM [dbo].[ActivityRecords] AS [Extent2]
WHERE [Limit1].[id] = [Extent2].[person_id] ) AS [Limit2]
LEFT OUTER JOIN [dbo].[Streets] AS [Extent3]
ON [Limit1].[street_id] = [Extent3].[id]
LEFT OUTER JOIN [dbo].[Streets] AS [Extent4] /* <-- Seriously? */
ON [Limit1].[street_id] = [Extent4].[id]
LEFT OUTER JOIN [dbo].[Cities] AS [Extent5]
ON [Extent4].[city_id] = [Extent5].[id]
LEFT OUTER JOIN [dbo].[Streets] AS [Extent6] /* <-- Come on! */
ON [Limit1].[street_id] = [Extent6].[id]
LEFT OUTER JOIN [dbo].[Cities] AS [Extent7] /* <-- Hey! */
ON [Extent6].[city_id] = [Extent7].[id]
LEFT OUTER JOIN [dbo].[Countries] AS [Extent8]
ON [Extent7].[country_id] = [Extent8].[id]
当我刚刚删除组连接中的单行连接时
...(p, ar) => new { p = p, ar = ar } ...
它工作正常并且加入每个 table 一次。
我试图在 join 之前包含 tables,但没有成功。唯一可行的是在 join 之前选择所有 person-streets-cities,但问题是它会加载所有记录before 削减前 10,实际上我有很多繁重的计算列(这个查询,当问题仍然可见时,如果删除 Skip() 会简单得多 和 Take(),但保留 GroupJoin() 和 FirstOrDefault()) .
所以,我的问题是:如何通知 EF 不要多次包含相同的 tables,是否有解决方法?为什么它在单行连接后开始失去导航属性链的跟踪?
这确实是 EF 查询编译中的错误,因此从 EF 6.1.1 升级到 EF 6.1.2 解决了这个问题.
我有一个像 Person 这样的模型,它可以住在 Street 和 Street位于城市,而城市则位于国家。还有一些 ActivityRecords 用于一些 Persons.
public class Country
{
[Key]
public int id { get; set; }
public string name { get; set; }
}
public class City
{
[Key]
public int id { get; set; }
public string name { get; set; }
[ForeignKey("Country")]
public int country_id { get; set; }
public virtual Country Country { get; set; }
}
public class Street
{
[Key]
public int id { get; set; }
public string name { get; set; }
[ForeignKey("City")]
public int city_id { get; set; }
public virtual City City { get; set; }
}
public class Person
{
[Key]
public int id { get; set; }
ForeignKey("Street")]
public int? street_id { get; set; }
public virtual Street Street { get; set; }
//no connection to ActivityRecord[]
}
public class ActivityRecord
{
[Key]
public int id { get; set; }
public string desc { get; set; }
[ForeignKey("Person")]
public int? person_id { get; set; }
public virtual Person Person { get; set; }
}
我需要列出一部分人员信息,包括他们在国家/地区的地址以及其中一项活动(如果有的话)(否则为空)。我故意删除了所有细节和列以简化示例。
所以,我在我的代码中做到了这一点:
context.Persons.AsNoTracking().OrderBy(p => p.id).Skip(0).Take(10).GroupJoin(
context.ActivityRecords,
p => p.id,
ar => ar.person_id,
(p, ar) => new { p = p, ar = ar.FirstOrDefault() } //join 1 or 0 entries
).Select(result => new
{
id = result.t.id,
street = result.t.Street.name,
city = result.t.Street.City.name,
country = result.t.Street.City.Country.name
}).ToArray();
当我检查 EF 生成的查询时,我多次看到相同 table 上的左外连接(街道、城市):
SELECT
[Limit1].[id] AS [id],
[Extent3].[name] AS [name],
[Extent5].[name] AS [name1],
[Extent8].[name] AS [name2]
FROM (SELECT TOP (10) [Extent1].[id] AS [id], [Extent1].[street_id] AS [street_id]
FROM ( SELECT [Extent1].[id] AS [id], [Extent1].[street_id] AS [street_id], row_number() OVER (ORDER BY [Extent1].[id] ASC) AS [row_number]
FROM [dbo].[Persons] AS [Extent1]
) AS [Extent1]
WHERE [Extent1].[row_number] > 0
ORDER BY [Extent1].[id] ASC ) AS [Limit1]
OUTER APPLY (SELECT TOP (1) [Extent2].[id] AS [id]
FROM [dbo].[ActivityRecords] AS [Extent2]
WHERE [Limit1].[id] = [Extent2].[person_id] ) AS [Limit2]
LEFT OUTER JOIN [dbo].[Streets] AS [Extent3]
ON [Limit1].[street_id] = [Extent3].[id]
LEFT OUTER JOIN [dbo].[Streets] AS [Extent4] /* <-- Seriously? */
ON [Limit1].[street_id] = [Extent4].[id]
LEFT OUTER JOIN [dbo].[Cities] AS [Extent5]
ON [Extent4].[city_id] = [Extent5].[id]
LEFT OUTER JOIN [dbo].[Streets] AS [Extent6] /* <-- Come on! */
ON [Limit1].[street_id] = [Extent6].[id]
LEFT OUTER JOIN [dbo].[Cities] AS [Extent7] /* <-- Hey! */
ON [Extent6].[city_id] = [Extent7].[id]
LEFT OUTER JOIN [dbo].[Countries] AS [Extent8]
ON [Extent7].[country_id] = [Extent8].[id]
当我刚刚删除组连接中的单行连接时
...(p, ar) => new { p = p, ar = ar } ...
它工作正常并且加入每个 table 一次。
我试图在 join 之前包含 tables,但没有成功。唯一可行的是在 join 之前选择所有 person-streets-cities,但问题是它会加载所有记录before 削减前 10,实际上我有很多繁重的计算列(这个查询,当问题仍然可见时,如果删除 Skip() 会简单得多 和 Take(),但保留 GroupJoin() 和 FirstOrDefault()) .
所以,我的问题是:如何通知 EF 不要多次包含相同的 tables,是否有解决方法?为什么它在单行连接后开始失去导航属性链的跟踪?
这确实是 EF 查询编译中的错误,因此从 EF 6.1.1 升级到 EF 6.1.2 解决了这个问题.