构建 NHibernate DTO 的最佳方法

发布于 2024-08-06 09:52:42 字数 1319 浏览 6 评论 0原文

我是 NHibernate(和 ORMS)的新手,并试图掌握它提供的无数不同选项。作为参考,我将 Fluent NHibernate 与单独的业务对象一起使用,而这些对象又纯粹使用 DTO 进行数据访问。我的应用程序架构必须同时支持 Windows 和 Web“前端”。

我的困惑是一般方法之一,因为似乎有很多选择。我的 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,以上都不是:)

I'm new to NHibernate (and ORMS) and trying to come to grips with the myriad of different options it presents. For reference, I'm using Fluent NHibernate with seperate business objects which in turn use DTO's purely for data access. My application architecture must support both windows and web "front ends".

My quandry is one of general approach as there seem to be so many options. My DTO's look something like the sample below. Each DTO has a reference to an ISession which is passed to them from the BO. They are responsible for their own load and save:

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)...

First of all:
Is this the correct approach to take - should the DTO have the ability to save and load itself?

Secondly:
Regardless of where the save/load code lies, should you use the same ISession for the lifetime or an object, or should they have a ref to the ISessionFactory and open a new session every time database interaction is required?

    // 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

Of course there's always option 3, none of the above :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

指尖上的星空 2024-08-13 09:52:42

一般来说,DTO 不包含行为(如保存、加载),也不包含它们如何持久化的知识(ISession)。听起来您真正创建的是一个数据层。理想情况下,您的业务层也不应该了解 ISession。也就是说,您可以根据需要快捷地简化此分层,但如果您的 ORM 渗透到所有层,则以后可能很难更改为不同的 ORM。

对于 ISession 生命周期管理,您必须决定是否要使用 UnitOfWork 模式,该模式基本上表示每个用户请求都会获得一个新的 ISession。 ISession 生命周期还有其他选项,并且您在这方面确实不受限制。通常,可能存在围绕 Web 应用程序、Windows 应用程序与任何其他应用程序类型的最佳实践,但您没有指定您正在编写哪种应用程序。

In general, DTOs do not contain behavior (like Save, Load) and do not contain knowledge of how they get persisted (ISession). It sounds like what you are really creating is a data layer. Your business layer ideally shouldn't know about ISession either. That said, you can shortcut this layering all you want as it fits your needs, but it will likely be difficult to change to a different ORM later if your ORM bleeds through all your layers.

For ISession lifetime management, you have to decide if you are going to use the UnitOfWork pattern, which basically says every user request gets a new ISession. There are other options for ISession lifetime as well and you really aren't limited in that regard. Often, there may be best practices around web apps vs. windows apps vs. whatever other application types, but you didn't specify which you were writing.

时光是把杀猪刀 2024-08-13 09:52:42

将加载/保存代码与 DTO 分开。 DTO 对象只是底层数据的视图

执行查询时,通过使用转换返回 DTO。像这样的东西:

resultSet = session.CreateCriteria(typeof(MyDataObject))
    .Add(query criteria, etc.)
    .SetResultTransformer(Transformers.AliasToBean<MyDTOObject>())
    .List<IMyDTOObject>()

Keep your loading/saving code separate from your DTOs. The DTO objects are only views of the underlying data.

When doing your queries, return the DTOs by using a transformation. Something like this:

resultSet = session.CreateCriteria(typeof(MyDataObject))
    .Add(query criteria, etc.)
    .SetResultTransformer(Transformers.AliasToBean<MyDTOObject>())
    .List<IMyDTOObject>()
微暖i 2024-08-13 09:52:42

DTO 旨在成为“数据传输对象”。也就是说,用于在系统中传递值或值集合的哑对象。他们不应该负责保存自己,甚至不应该将 1-1 映射到域层中的域对象。

DTO's are meant to be "data transfer objects". That is, dumb objects used for passing values or collections of values around in your system. They shouldn't be responsible for persisting themselves, or even map 1-1 to domain objects in your domain layer.

浅语花开 2024-08-13 09:52:42

ISession 的打开/关闭成本非常低。保持打开时间过长的问题是连接池无法重用连接,直到超时或其他原因。这可能是多用户应用程序中的问题。

在您的场景中,我可能会采用面向服务的方法来存储检索数据。这意味着 DTO 只能在服务边界内内部使用。如果您需要复制看起来相同的对象,我建议您查看 AutoMapper 这是为这个特定的目的。如果您有仅 Windows 或仅 Web 项目,那么这不是问题。就是当你混合的时候。您无法像在 Web 应用程序中那样在 Windows 应用程序中处理会话。

The ISession is very inexpensive to open/close. The problem with keeping it open for too long is that the connection pool can't reuse the connection until it times out or what not. This could be a problem in a multiuser application.

In your scenario I'd probably go for a service oriented approach to store retrieve data. meaning the DTO would only be used internally within the service boundaries. If you need to copy objects that look the same I suggest you have a look at AutoMapper which was created for this specific purpose. If you have a windows only or web only project then it's not a problem. It's when you mix. You can't handle the sessions the same way in a Windows app as in a Web app.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文