我是NHibernate(和ORMS)的新手,并试图掌握它所呈现的无数不同选项。作为参考,我使用Fluent NHibernate和单独的业务对象,而这些对象又使用DTO纯粹用于数据访问。我的应用程序架构必须同时支持Windows和Web“前端”。
我的quandry是一种通用方法,因为似乎有很多选择。我的DTO看起来像下面的示例。每个DTO都引用了一个从BO传递给它们的ISession。他们负责自己的负担并保存:
public class EmployeeDTO...
// Data Properties to be persisted to the database
public virtual int Id { get; private set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual ISession Session { get; set; }
// Save logic
public virtual void Save()
{
var transaction = Session.BeginTransaction();
Session.SaveOrUpdate(this);
transaction.Commit();
}
// Load logic
public virtual void Load(int id)...
首先: 这是正确的方法吗 - DTO是否有能力自行保存和加载?
其次: 无论保存/加载代码在哪里,您是否应该在生命周期或对象中使用相同的ISession,还是应该在每次需要数据库交互时都有对ISessionFactory的引用并打开一个新会话?
// Open a new session every time I interact with the repository
var session = FluentSupport.SessionFactory.OpenSession();
var transaction = Session.BeginTransaction();
Session.SaveOrUpdate(this);
transaction.Commit();
session.Close();
// Close the session when I'm done
当然总有选项3,以上都不是:)
答案 0 :(得分:10)
通常,DTO不包含行为(如Save,Load),并且不包含它们如何被持久化的知识(ISession)。听起来你真正创建的是一个数据层。理想情况下,您的业务层也不应该了解ISession。也就是说,您可以根据自己的需要快速分割所需的分层,但如果您的ORM渗透到所有图层,则可能很难在以后更改为其他ORM。
对于ISession生命周期管理,您必须决定是否要使用UnitOfWork模式,该模式基本上表示每个用户请求都会获得新的ISession。对于ISession的生命周期还有其他选择,你在这方面确实不受限制。通常,围绕Web应用程序与Windows应用程序相比,可能存在最佳实践,而不是其他任何应用程序类型,但您没有指定您正在编写的内容。
答案 1 :(得分:9)
将您的加载/保存代码与DTO分开。 DTO对象只是基础数据的视图。
进行查询时,使用转换返回DTO。像这样:
resultSet = session.CreateCriteria(typeof(MyDataObject))
.Add(query criteria, etc.)
.SetResultTransformer(Transformers.AliasToBean<MyDTOObject>())
.List<IMyDTOObject>()
答案 2 :(得分:3)
DTO是“数据传输对象”。也就是说,用于在系统中传递值或值集合的哑对象。他们不应该对自己的持久性负责,或者甚至将1-1映射到域图层中的域对象。
答案 3 :(得分:2)
ISession打开/关闭非常便宜。将其保持打开状态的问题是连接池在超时或不能超时之前无法重用连接。这可能是多用户应用程序中的问题。
在您的场景中,我可能会采用面向服务的方法来存储检索数据。这意味着DTO只能在服务边界内部使用。如果您需要复制看起来相同的对象,我建议您查看为此特定目的创建的AutoMapper。如果您只有Windows或仅限Web项目,那么这不是问题。这是你混合的时候。您无法在Windows应用程序中以与在Web应用程序中相同的方式处理会话。