2012-01-24 131 views
0

延迟加载我单独我的域逻辑从我的web服务逻辑与NHibernate流利,Web服务和automapper

这是我的域名,实际上从NHibernate的

public static IList<Location> LoadReturnLocationsFromDatabase(DateTime lastUpdateTime) 
{ 
    using (var session = NHibernateHelper.OpenSession()) 
    { 
     // retreive all stores and display them 
     using (session.BeginTransaction()) 
     { 
      var locations = session.CreateCriteria(typeof(Location)).Add(Expression.Gt("LastUpdatedTime", lastUpdateTime)).SetMaxResults(10).List<Location>(); 
      return locations; 
     } 
    } 
} 

此数据获取数据然后返回到Web服务我用Automapper复制它,以不公开的数据库访问对象的网络服务,并保持所有的东西独立。

public IList<GetLocationDetailsResponse> GetLocationUpdate(DateTime lastUpdateTimeDT) 
{ 

    Mapper.CreateMap<Location, GetLocationDetailsResponse>(); 

    IList<Location> locations = WhygoDomain.GetLocations.LoadReturnLocationsFromDatabase(lastUpdateTimeDT); 

    IList<GetLocationDetailsResponse> getLocationDetails = Mapper.Map<IList<Location>, IList<GetLocationDetailsResponse>>(locations); 
    return getLocationDetails; 
} 

我的问题是我不能做的映射,除非我指定的位置和状态之间的关系是不懒加载,因为Web服务是外:在数据

using (var session = NHibernateHelper.OpenSession()) 

域。

延迟加载似乎是做这样的事情的首选方法,所以我想知道如果这种方法好不好?这是一个数据导出服务,将导出内存使用情况等最终可能会有问题。

如果我需要改变这一点,是这个问题的原因我的代码结构?如果是这样,我怎么能保持我的域逻辑独立,并解决这个问题?

+0

您是否有AOP框架? –

回答

2

预先抓取

您可以避免这个问题通过与地方一起热切取状态达到更好的性能 - 否则,你有什么叫做“选择N + 1”的问题。见Ayende的博客,就是一个很好的解释: http://ayende.com/blog/1328/combating-the-select-n-1-problem-in-nhibernate

实质上,每次访问不同的location.State时都会执行一个单独的SQL查询,这可能意味着您的案例中多达11次往返数据库。如果位置查询包含在LEFT OUTER JOIN的状态,那么所有需要的数据可以在一个单一的往返到数据库中读取。

在你的情况,下面的查询可能会更好地工作:

var locations = session.CreateCriteria(typeof(Location)) 
    .Add(Expression.Gt("LastUpdatedTime", lastUpdateTime)) 
    .SetMaxResults(10) 
    .SetFetchMode("State", FetchMode.Eager) 
    .List<Location>(); 

依赖倒置

您遇到的问题阐明一个事实,即GetLocations不足够了解的情况来定负责创建和销毁NHibernate会话。 NHibernate会话的创建至少需要向上移动一层。当然,还有在做这一切,就像使用IoC容器的更优雅的方式,但这里的一些快速和肮脏的代码来说明我的意思:

public IList<GetLocationDetailsResponse> GetLocationUpdate(DateTime lastUpdateTimeDT) 
{ 
    using (var session = NHibernateHelper.OpenSession()) 
    { 
     var locations = GetLocations.LoadReturnLocationsFromDatabase(session, lastUpdateTimeDT); 
     return Mapper.Map<IList<Location>, IList<GetLocationDetailsResponse>>(locations); 
    } 
} 

最后一点:AutoMapper的Mapper.CreateMap是静态的设置代码,只需要在应用程序启动时执行一次。 Global.asax是该类型代码的最佳位置。

2

,因为你需要一个开放的会议,能够从连接的域对象分离的自动映射对象映射,你必须确保会议是开放的,而你是自动映射。您可以考虑将您的使用声明移至Web服务调用,而不是将其用于域方法中。

+0

我知道你在说什么,但似乎摆脱了分离的Web服务和域的整个点...也许我已经分离它已经虽然... – iKode

+0

我不知道这是最好不是延迟加载数据 – iKode

+0

@iKode:如果在加载后直接访问其所有属性,那么延迟加载数据没有任何意义。 –