C# 这个EF查询可以优化吗?
我不熟悉实体框架,不确定何时使用即时加载和C# 这个EF查询可以优化吗?,c#,entity-framework,entity-framework-4,linq-to-entities,C#,Entity Framework,Entity Framework 4,Linq To Entities,我不熟悉实体框架,不确定何时使用即时加载和Include,何时使用带有Select的LINQ查询,以及何时根据需要加载实体。我也不知道EF是否以及何时缓存实体。(是的,我最终会阅读文档:-) 我正在ASP.NETMVC网站内部构建一个消息传递系统,性能将非常重要。想象一下下面的场景 当蕾哈娜进入她的收件箱时,她需要看到一个邮件列表,每个邮件都有发件人的姓名和图片。想象一下约翰为他的新歌写了蕾哈娜的歌词。在她的收件箱里,有一条有约翰照片的信息。当约翰走进他的发件箱时,他看到了与蕾哈娜的名字和照片相
Include
,何时使用带有Select
的LINQ查询,以及何时根据需要加载实体。我也不知道EF是否以及何时缓存实体。(是的,我最终会阅读文档:-)
我正在ASP.NETMVC网站内部构建一个消息传递系统,性能将非常重要。想象一下下面的场景
当蕾哈娜进入她的收件箱时,她需要看到一个邮件列表,每个邮件都有发件人的姓名和图片。想象一下约翰为他的新歌写了蕾哈娜的歌词。在她的收件箱里,有一条有约翰照片的信息。当约翰走进他的发件箱时,他看到了与蕾哈娜的名字和照片相同的信息
因此,当我们从数据库中获取消息时,可能需要发送者和接收者的个人资料图片。想象一下下面的查询:
private static Func<MyEntities, int, Message> _getMessageByIdQuery = CompiledQuery.Compile(
( MyEntities ctx, int messageId ) => ctx.Messages
.Include( "SenderUser" )
.Include( "SenderUser.UserProfile.Image" )
.Include( "RecipientUser" )
.Include( "RecipientUser.UserProfile.Image" )
.SingleOrDefault( message => message.ID == messageId ) );
private static Func\u getMessageByIdQuery=CompiledQuery.Compile(
(MyEntities ctx,int messageId)=>ctx.Messages
.包括(“发送者”)
.Include(“SenderUser.UserProfile.Image”)
.包括(“接收方用户”)
.Include(“RecipientUser.UserProfile.Image”)
.SingleOrDefault(message=>message.ID==messageId));
这个查询是否有效?考虑到User.ID
和UserProfile.UserID
是一对一的,有没有办法在不加载SenderUser.UserProfile.Image的情况下加载SenderUser.UserProfile.Image
?我想我需要使用LINQ JOIN来实现这一点。这是正确的吗
如果只需要一个字段(例如,仅从UserProfile
加载ImageID
),使用LINQ避免加载所有字段是否更有效
使用Load
在代码中的某个地方执行同样的操作是否更好
这样的查询每次都会进入数据库吗?想象一下,我们有一千条信息,都来自同一个人。我们会每次都查询他的图像吗
我正在使用EF4和ASP.NETMVC3
谢谢。一种方法是直接从查询发送自定义显示/数据对象,这样您就不需要加载额外的对象。例如:
var dto = ctx.Messages
.Where(whereclause)
.Select(m=> new DTOTYPE
{Id = m.Id,
Content= m.Content,
SenderId = m.SenderUser.Id,
SenderImage = m.SenderUser.UserProfile.Image,
SenderImageId = m.SenderUser.UserProfile.ImageId})
//more fields if you need any
这将取决于你的场景,但这样你就不必做疯狂的包括所有。但是您需要管理视图/数据对象,因为对于许多不同的屏幕和视图,它们可能无法控制。希望这有帮助 没有人能告诉您代码的性能,您必须进行基准测试。
是,如果使用联接,则可以避免加载SenderUser。如果您想知道如何查看生成的sql代码,请查看。使用@AD.Net建议的投影。使用投影时,您可以传输您真正需要的数据,而不是传输包含您从未使用过的特性的整个对象。请注意,每次查询数据库中的消息时,都会加载图片
如果您计划显示来自同一用户的更多消息,请在单独的查询中仅加载图像一次!此外,收件人是否真的需要加载其图像?如果是,为什么不在他登录时只加载一次图像,并将其保存在会话中,而不是为她收件箱中的每封邮件加载相同的数据?感谢您的回复!想象一下约翰给蕾哈娜发了很多信息。她会收到一个装满他的邮件的收件箱(还有他的照片!),但在列表加载之前,不知道他的照片会重复。所以,先加载邮件,然后在单独的查询中加载所有发件人的图像。否则,您可以接收来自同一用户的100条消息,并将其图像加载100次。谢谢。最后,我尝试了手动join
s和使用Select
进行投影,看起来Select
生成了稍微重一些的连接,但更易于维护,所以我将保持原样。