gpt4 book ai didi

c# - LINQ-to-Entities Include 的奇怪行为

转载 作者:行者123 更新时间:2023-11-29 03:11:22 25 4
gpt4 key购买 nike

我意识到我没有完全理解 LINQ-to-Entities 中的 Include 方法。

例如,以下面的两个代码片段为例。我希望它们产生相同的输出(尽管第一个版本可能更有效,因为它避免了 JOIN)。

// Snippet 1
using (var db = new Db()) {
var author = db.Authors.First();
db.LoadProperty<Author>(author, o => o.Books);
foreach (var book in author.Books) {
db.LoadProperty<Book>(book, o => o.Editions);
foreach (var edition in book.Editions)
Response.Write(edition.Id + " - " + edition.Title + "<br />");
}
}

Response.Write("<br />");

// Snippet 2
using (var db = new Db()) {
var author = db.Authors.Include("Books.Editions").First();
foreach (var book in author.Books) {
foreach (var edition in book.Editions)
Response.Write(edition.Id + " - " + edition.Title + "<br />");
}
}

但是每个片段的输出是不同的:

1 - Some Book First Edition
2 - Another Book First Edition
3 - Another Book Second Edition
4 - Another Book Third Edition

8 - Some Book First Edition
9 - Another Book First Edition

第一个片段正确输出了 {Edition Id} - {Edition Title},而第二个片段意外地输出了 {Book Id} - {Edition Title} 并且只给出了每本书的第一版。

这是怎么回事?有没有一种方法可以使用 Include 实现所需的输出?

编辑 1:MySql 数据看起来像(更正):

Authors         = { { Id = 1, Name = "Some Author" } }

Books = { { Id = 8, AuthorId = 1 },
{ Id = 9, AuthorId = 1 } }

Editions = { { Id = 1, Title = "Some Book First Edition" },
{ Id = 2, Title = "Another Book First Edition" },
{ Id = 3, Title = "Another Book Second Edition" },
{ Id = 4, Title = "Another Book Third Edition" } }

EditionsInBooks = { { BookId = 8, EditionId = 1 },
{ BookId = 9, EditionId = 2 },
{ BookId = 9, EditionId = 3 },
{ BookId = 9, EditionId = 4 } }

请注意,Id = 8Id = 9 不存在 Edition

上面的代码是我的完整代码,在Page_Load中是一个空的测试页。

编辑 2:我测试了以下内容,它们没有任何区别:

  1. var author = db.Authors.Include("Books.Editions").AsEnumerable().First();
  2. var author = db.Authors.Include("Books.Editions").Single(o => o.Id == 1);
  3. var author = db.Authors.Include("Books").Include("Books.Editions").First();

编辑 3:如果我启用延迟加载,则以下内容有效(在代码段 2 中):

var author = db.Authors.First();

(我想这基本上与代码段 1 相同。)

但是,无论延迟加载如何,这仍然会返回奇怪的输出:

var author = db.Authors.Include("Books.Editions").First();

编辑 4:我真的很抱歉,但我歪曲了上面的表结构。 (我正经历其中的一天。)现在已更正,以显示多对多关系。请参阅编辑 1。

也是

的输出
((ObjectQuery)db.Authors.Include("Books.Editions").AsEnumerable())
.ToTraceString()

SELECT
`Project1`.`Id`,
`Project1`.`Name`,
`Project1`.`C2` AS `C1`,
`Project1`.`id1`,
`Project1`.`AuthorId`,
`Project1`.`C1` AS `C2`,
`Project1`.`id2`,
`Project1`.`Title`
FROM (SELECT
`Extent1`.`Id`,
`Extent1`.`Name`,
`Join2`.`Id` AS `id1`,
`Join2`.`AuthorId`,
`Join2`.`Id` AS `id2`,
`Join2`.`Title`,
CASE WHEN (`Join2`.`Id` IS NULL) THEN (NULL)
WHEN (`Join2`.`BookId` IS NULL) THEN (NULL)
ELSE (1) END AS `C1`,
CASE WHEN (`Join2`.`Id` IS NULL) THEN (NULL)
ELSE (1) END AS `C2`
FROM `authors` AS `Extent1`
LEFT OUTER JOIN (SELECT
`Extent2`.`Id`,
`Extent2`.`AuthorId`,
`Join1`.`BookId`,
`Join1`.`EditionId`,
`Join1`.`Id` AS `Id1`,
`Join1`.`Title`
FROM `books` AS `Extent2`
LEFT OUTER JOIN (SELECT
`Extent3`.`BookId`,
`Extent3`.`EditionId`,
`Extent4`.`Id`,
`Extent4`.`Title`
FROM `editionsinbooks` AS `Extent3`
INNER JOIN `editions` AS `Extent4`
ON `Extent4`.`Id` = `Extent3`.`EditionId`) AS `Join1`
ON `Extent2`.`Id` = `Join1`.`BookId`) AS `Join2`
ON `Extent1`.`Id` = `Join2`.`AuthorId`) AS `Project1`
ORDER BY
`Project1`.`Id` ASC,
`Project1`.`C2` ASC,
`Project1`.`id1` ASC,
`Project1`.`C1` ASC

CASE 语句很有趣,因为我的 MySql 字段都不能为 null。

最佳答案

Entity Framework 的提供程序在 LINQ 语句中编译 First() 表达式时可能存在错误。当涉及 Include 时偶尔会出现奇怪的情况:http://wildermuth.com/2008/12/28/Caution_when_Eager_Loading_in_the_Entity_Framework

尝试将第二个代码段重写为:

using (var db = new Db()) {
var author = db.Authors.Include("Books.Editions").AsEnumerable().First();
foreach (var book in author.Books)
{
foreach (var edition in book.Editions)
{
Response.Write(edition.Id + " - " + edition.Title + "<br />");
}
}
}

如果这修复了您的输出,那么它肯定是 First() 方法。

编辑:关于您的第三次编辑与代码段 1 执行相同操作的说法是正确的。我无法理解该 include 语句如何将事情搞得如此糟糕。我唯一可以鼓励的是查看它生成的 SQL 查询:

var sql = ((System.Data.Objects.ObjectQuery)db.Authors.Include("Books.Editions").AsEnumerable().First()).ToTraceString();

编辑 2:鉴于生成了疯狂的 sql 输出,问题很可能出在 EF 的 MySQL 提供程序中。

关于c# - LINQ-to-Entities Include 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7808218/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com