我从我的网络服务逻辑中分离我的域逻辑
这是来自 my domain ,实际上是从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将其复制,以便不将数据库访问对象公开给Web服务并保持所有内容分离。
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 :(得分: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 Sessions负责的情况不够了解这一事实。 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是这类代码的最佳位置。