C# 有人能解释为什么这两个linq查询返回不同的结果吗?
我有两个linq(到EF4)查询,它们返回不同的结果。第一个查询包含正确的结果,但格式/投影不正确 第二个查询是我想要的,但它缺少一些数据 模式 问题1 请注意属性C# 有人能解释为什么这两个linq查询返回不同的结果吗?,c#,.net,sql,linq,linq-to-entities,C#,.net,Sql,Linq,Linq To Entities,我有两个linq(到EF4)查询,它们返回不同的结果。第一个查询包含正确的结果,但格式/投影不正确 第二个查询是我想要的,但它缺少一些数据 模式 问题1 请注意属性GameFile。它不是空的。这很好:)注意到linq查询了吗?我急切地加载一个日志条目,然后急切地加载一个游戏文件(对于每个急切加载的日志条目) 这就是我想要的->对于每个渴望加载的LogEntry,请渴望加载GameFile。但是这个预测结果是错误的 好的。。接下来 问题2 注意:上面的图片有一个打字错误。。。请注意,图像
GameFile
。它不是空的。这很好:)注意到linq查询了吗?我急切地加载一个日志条目
,然后急切地加载一个游戏文件
(对于每个急切加载的日志条目)
这就是我想要的->对于每个渴望加载的LogEntry
,请渴望加载GameFile
。但是这个预测结果是错误的
好的。。接下来
问题2
注意:上面的图片有一个打字错误。。。请注意,图像键入时,包含关联的键入代码是正确的(即LogEntry.GameFile
)
现在更正投影->所有日志条目结果。但是请注意,GameFile
属性现在是空的?我不知道为什么:(我以为我正确地加载了正确的链。所以这是正确的投影,但结果不正确
强制性存储库代码。
public IQueryable GetConnectedClient(
字符串[]包括关联)
{
返回Context.ConnectedClients
.包括关联(包括关联)
.AsQueryable();
}
公共静态类扩展
{
公共静态IQueryable包含关联(
此IQueryable源,字符串包括关联)
{
如果(!string.IsNullOrEmpty(includeAssociation))
{
var objectQuery=源作为objectQuery;
if(objectQuery!=null)
{
返回objectQuery.Include(includeAssociation);
}
}
返回源;
}
公共静态IQueryable包含关联(
此IQueryable源,参数字符串[]包括关联)
{
如果(包括关联!=null)
{
foreach(includeAssociations中的字符串关联)
{
来源=来源。包括关联(关联);
}
}
返回源;
}
}
更新
- 1:修复了代码示例中注意到的一些打字错误
- 2:添加了存储库代码,以帮助任何感到困惑的人
看来您还需要一个存储库方法来为您实现这一点;\u connectedclients respository.getlogentriesfconnectedclients()
我怀疑Craig Stuntz的建议可能管用,但如果不行,以下建议肯定管用:
var xxxx =_connectedClientRepository
.GetConnectedClients(new[] { "LogEntry", "LogEntry.GameFile" })
.AsExpandable()
.Where(predicate)
.ToList() // execute query
.Select(cp => cp.LogEntry); // use linq-to-objects to project the result
Include()
处理查询结果,而不是中间查询。您可以在本文中阅读更多关于Include()
的内容。因此,一种解决方案是将Include()
应用于整个查询,如下所示:
var q = ((from cp in _connectedClientRepository.GetConnectedClients()
.AsExpandable()
.Where(predicate)
select cp.LogEntry)
as ObjectQuery).Include("GameFile").ToList();
那可能行得通,但很难看。我们能做得更好吗
我可以想出两种方法来解决这个问题。这主要取决于您是否确实需要返回实体类型。如果不查看代码的其余部分,我就不能说是否需要返回实体类型。通常,您需要在更新(或修改)时返回实体类型它们。如果您选择用于显示或计算目的,则返回POCO而不是实体类型通常是一种更好的策略。您可以使用执行此操作,当然它在EF 1中也适用。在这种情况下,您可以将存储库方法更改为返回POCO类型:
public IQueryable<ClientInfo> GetConnectedClients()
{
return from cp in _context.Clients
where // ...
select new ClientInfo
{
Id = cp.Id,
ClientName = cp.ClientName,
LogEntry = new LogEntryInfo
{
LogEntryId = cp.LogEntry.LogEntryId,
GameFile = new GameFileInfo
{
GameFileId = cp.LogEntry.GameFile.GameFileId,
// etc.
},
// etc.
},
// etc.
};
}
public IQueryable GetConnectedClients()
{
在_context.Clients中从cp返回
where/。。。
选择new ClientInfo
{
Id=cp.Id,
ClientName=cp.ClientName,
LogEntry=newlogentryinfo
{
LogEntryId=cp.LogEntry.LogEntryId,
GameFile=新的GameFileInfo
{
GameFileId=cp.LogEntry.GameFile.GameFileId,
//等等。
},
//等等。
},
//等等。
};
}
请注意,当您使用projection时,没有即时加载、延迟加载和显式加载。只有您的意图,以查询的形式表达。即使您在存储库之外进一步编写查询,LINQ提供程序也会找出您需要的内容
另一方面,您可能需要返回实体类型而不是POCO,因为您打算更新它们。在这种情况下,我会为日志条目编写一个单独的存储库方法,正如Tomas所建议的那样。但我只会在打算更新它们时才这样做,我可能会将其作为更新方法编写,而不是“Get”方法。您不需要从发送给GetConnectedClient的参数中删除“LogEntry”吗?我的猜测是:投影改变了结果的形状,因此包含的不再匹配。这有效吗?((从_ConnectedClientRespository.GetConnectedClient()中的cp。AsExpandable()。其中(谓词)选择cp.LogEntry)作为ObjectQuery)。包括(“游戏文件”).ToList()
?@Lasse V.Karlsen:我试过了,但没用。我也试过LogEntry.GameFile和LogEntry,LogEntry.GameFile。但也没用。@Craig Stuntz:有趣的一点……我怀疑是这样的。我很快会尝试。但是你有没有链接到其他人详细解释这个问题呢?你也注意到了吗?没别的了比通常的Include
文档更重要的是,它适用于ObjectQuery
,而T
是很重要的。这可能会有帮助:嗯。我想我需要尊重你的意见。我的存储库方法返回IQueriable,linq查询的其余部分执行筛选,而不是hardco
var xxxx =_connectedClientRepository
.GetConnectedClients(new[] { "LogEntry", "LogEntry.GameFile" })
.AsExpandable()
.Where(predicate)
.ToList() // execute query
.Select(cp => cp.LogEntry); // use linq-to-objects to project the result
var q = ((from cp in _connectedClientRepository.GetConnectedClients()
.AsExpandable()
.Where(predicate)
select cp.LogEntry)
as ObjectQuery).Include("GameFile").ToList();
public IQueryable<ClientInfo> GetConnectedClients()
{
return from cp in _context.Clients
where // ...
select new ClientInfo
{
Id = cp.Id,
ClientName = cp.ClientName,
LogEntry = new LogEntryInfo
{
LogEntryId = cp.LogEntry.LogEntryId,
GameFile = new GameFileInfo
{
GameFileId = cp.LogEntry.GameFile.GameFileId,
// etc.
},
// etc.
},
// etc.
};
}