C# 一种无需多个DB调用的查询方法

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(

在一个web应用程序上,我正在使用带有ASP.NET-MVC的NHibernate进行开发,我们在页面加载方面遇到了一些严重的延迟,所以我被赋予了调查和重构的任务

当我浏览代码时,有很多这样的调用:

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
方法调用将导致所有客户端记录从数据库加载到内存中

我建议每个请求使用一个NHibernate
ISession
,而不是每个方法调用使用一个
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();