C# 一种无需多个DB调用的查询方法
在一个web应用程序上,我正在使用带有ASP.NET-MVC的NHibernate进行开发,我们在页面加载方面遇到了一些严重的延迟,所以我被赋予了调查和重构的任务 当我浏览代码时,有很多这样的调用:C# 一种无需多个DB调用的查询方法,c#,asp.net-mvc,nhibernate,C#,Asp.net Mvc,Nhibernate,在一个web应用程序上,我正在使用带有ASP.NET-MVC的NHibernate进行开发,我们在页面加载方面遇到了一些严重的延迟,所以我被赋予了调查和重构的任务 当我浏览代码时,有很多这样的调用: public static IEnumerable<Client> GetAllClients() { return new EntityManager<Client>() .GetAll<Client>() .Where(
public static IEnumerable<Client> GetAllClients()
{
return new EntityManager<Client>()
.GetAll<Client>()
.Where(x => x.IsDeleted == false || x.IsDeleted == null);
}
这是非常好的,因为它在进入数据库之前考虑了Where
子句。但是,我看到仍然有一些方法调用GetAll()
,然后在上面应用另一个,其中
:
var Clients = GetAllClients().Where(n => n.Location == "someCity");
我猜这首先使用会话调用GetAll()
,然后应用新的Where
并再次返回数据库?这是真的吗
有更好/更优雅的方法吗?是的,您的解决方案绝对正确。我不太了解NHibernate,但这个案例也类似于实体框架。使用session将避免对服务器的攻击,并首先准备一个查询。一旦查询准备好,它就会命中服务器 您也可以在这里找到NHibernate中相同where子句的示例 您还可以在Nhibernate中找到一个与IQueryable概念相关的好教程
是的,你的解决方案绝对正确。我不太了解NHibernate,但这个案例也类似于实体框架。使用session将避免对服务器的攻击,并首先准备一个查询。一旦查询准备好,它就会命中服务器 您也可以在这里找到NHibernate中相同where子句的示例 您还可以在Nhibernate中找到一个与IQueryable概念相关的好教程
是的,你的解决方案绝对正确。我不太了解NHibernate,但这个案例也类似于实体框架。使用session将避免对服务器的攻击,并首先准备一个查询。一旦查询准备好,它就会命中服务器 您也可以在这里找到NHibernate中相同where子句的示例 您还可以在Nhibernate中找到一个与IQueryable概念相关的好教程
是的,你的解决方案绝对正确。我不太了解NHibernate,但这个案例也类似于实体框架。使用session将避免对服务器的攻击,并首先准备一个查询。一旦查询准备好,它就会命中服务器 您也可以在这里找到NHibernate中相同where子句的示例 您还可以在Nhibernate中找到一个与IQueryable概念相关的好教程
这取决于
EntityManager
的GetAll
的结果类型。如果它是IQueryable
,则在命中数据库之前将应用where;如果它是IEnumerable
,或list,或array,则将在内存中执行where
因为GetAllClients
返回IEnumerable
对的后续调用,其中
将在内存中执行
另外,在第二个示例中,您可能希望使用
Query
(Linq)而不是QueryOver
。Linq和QueryOver是不同的查询引擎。这取决于EntityManager
的GetAll
的结果类型。如果它是IQueryable
,则在命中数据库之前将应用where;如果它是IEnumerable
,或list,或array,则将在内存中执行where
因为GetAllClients
返回IEnumerable
对的后续调用,其中
将在内存中执行
另外,在第二个示例中,您可能希望使用
Query
(Linq)而不是QueryOver
。Linq和QueryOver是不同的查询引擎。这取决于EntityManager
的GetAll
的结果类型。如果它是IQueryable
,则在命中数据库之前将应用where;如果它是IEnumerable
,或list,或array,则将在内存中执行where
因为GetAllClients
返回IEnumerable
对的后续调用,其中
将在内存中执行
另外,在第二个示例中,您可能希望使用
Query
(Linq)而不是QueryOver
。Linq和QueryOver是不同的查询引擎。这取决于EntityManager
的GetAll
的结果类型。如果它是IQueryable
,则在命中数据库之前将应用where;如果它是IEnumerable
,或list,或array,则将在内存中执行where
因为GetAllClients
返回IEnumerable
对的后续调用,其中
将在内存中执行
另外,在第二个示例中,您可能希望使用
Query
(Linq)而不是QueryOver
。Linq和QueryOver是不同的查询引擎。当您对数据访问进行过度抽象时,这是一个非常常见的问题
GetAllClients
方法中的List
方法调用将导致所有客户端记录从数据库加载到内存中
我建议每个请求使用一个NHibernateISession
,而不是每个方法调用使用一个ISession
。并使您的方法返回IQueryable
,而不是IEnumerable
。类似这样的内容(NHibernate 3.0+):
或进行投影:
var clientShortInfos = GetAllClients().Where(it => it.Location == "city")
.Select(it => new
{
Id = it.Id,
FullName = it.FullName
})
.ToList();
这允许您仅检索所需字段,而不是从数据库中检索所有字段
这里有一些有用的帖子:
- 当您对数据访问进行过度抽象时,这是一个非常常见的问题
GetAllClients
方法中的List
方法调用将导致所有客户端记录从数据库加载到内存中
我建议
using NHibernate;
using NHibernate.Linq;
public class EntityManager<T> {
private ISession _session;
public EntityManager(ISession session) {
_session = session;
}
public IQueryable<T> GetAllClients() {
return _session.Query<T>();
}
}
GetAllClients().Where(it => it.Location == "city").ToList();
var clientShortInfos = GetAllClients().Where(it => it.Location == "city")
.Select(it => new
{
Id = it.Id,
FullName = it.FullName
})
.ToList();