分离域模型和持久性模型时,如何跟踪变更问题? [英] How is Change Tracking an issue when separating the Domain Model and Persistence Model?

查看:155
本文介绍了分离域模型和持久性模型时,如何跟踪变更问题?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在这里阅读此问题:具有单独的域模型和DDD中的持久性模型

I was reading this question here: Having Separate Domain Model and Persistence Model in DDD

,并专门查看以下代码:

and specifically looking at this code:

public class ApplicationService
{
    private ITicketsRepository ticketsRepository;

    public ApplicationService(ITicketsRepository ticketsRepository)
    {
        this.ticketsRepository = ticketsRepository;
    }

    public bool IsTicketExpired(int ticketId)
    {
        Ticket persistanceModel = this.ticketsRepository.GetById(ticketId);
        TicketEntity domainModel = new TicketEntity(
            persistanceModel.Id,
            persistanceModel.Cost,
            persistanceModel.ExpiryDate);

        return domainModel.IsTicketExpired();
    }
}

此代码表示存在单独的域模型和持久性模型。我试图了解使用此方法的局限性。在整个Internet上,我读到有关使用NHibernate进行更改跟踪的问题,但是我不明白为什么。在将域模型映射回持久性模型之后,将处理变更跟踪。变更如何跟踪问题?一个有关如何跟踪变更的问题的实用示例将对我有所帮助。

This code means there is a separate Domain Model and Persistence Model. I am trying to understand what the limitations of using this approach are. All over the Internet I read about change tracking being an issue when using NHibernate, however I do not understand why. Change Tracking is dealt with after the domain model is mapped back to the persistence model. How is change tracking an issue? A practical example of how change tracking is an issue would help me.

更新
请参见以下代码:

Update Please see the code below:

//Repository
public Ticket GetTicket(int ticketId)
{
    return this.ticketsRepository.GetById(ticketId);
}

而我在应用程序服务中这样做:

and I do this in the application service:

//Application Service
Ticket ticket = applicationService.GetTicket(1);
ticket.Cost = .....
TicketEntity ticketEntity = AutoMapper.Map<TicketEntity>(ticket);
ticketEntity.DomainMethod();
ticket = AutoMapper.Map<Ticket>(ticketEntity);

Q1)是在此代码中丢失的ORM的好处,例如变更追踪?请注意,持久性对象是从存储库返回的,然后被映射到域对象,然后又回到相同的持久性对象。

Q1) Are the benefits of an ORM lost in this code e.g. change tracking? Notice that the persistence object is returned from the repository and then is mapped to a domain object and then back to the same persistence object.

Q2)NHibernate如何跟踪更改,即如何知道票证(持久性对象)在数据库中是票证1。

Q2) How does NHibernate track changes i.e. how does it know that Ticket(persistence object) is ticket 1 in the database. I guess it is not simply by the ID.

推荐答案

@MikeSW回答的大多数细节都是正确的。我只不同意变更跟踪。我的答案更多是关于NHibernate,而不是DDD。

Most of the details in answer from @MikeSW are correct; I only disagree with change tracking. My answer is more in terms of NHibernate than DDD.

是的,更改跟踪将是一个问题,但这取决于 ISession 被管理。此外,更改跟踪不仅会影响NHibernate的其他功能,例如会话级缓存,延迟加载等。

Yes, change tracking will be an issue but it depends on how the ISession is managed. Further, not only change tracking, it will also affect other features of NHibernate like Session Level Cache, Lazy Loading etc.

让我们假设 ISession 在请求级别进行管理,即每个请求一个 ISession 。而且下面提到的所有活动都是一个请求的一部分。

Let us assume that ISession is managed on request level i.e. one ISession per request. And all activities mentioned below are part of one single request.

public TicketEntity GetTicket(int ticketId)
{
    Ticket persistanceModel = this.ticketsRepository.GetById(ticketId);
    TicketEntity domainModel = new TicketEntity(
        persistanceModel.Id,
        persistanceModel.Cost,
        persistanceModel.ExpiryDate);

    return domainModel;
}

public void SaveTicket(TicketEntity ticketEntity)
{
    Ticket ticket = //Here, you have to map TicketEntity to Ticket
    this.ticketsRepository.Save(ticket);
}

现在,以下是同一请求中应用程序中的代码:

Now, following is the code somewhere in application in same request:

TicketEntity ticketEntity = applicationService.GetTicket(1);
ticketEntity.Cost = .....
.....
.....
applicationService.SaveTicket(ticketEntity);

NHibernate有能力跟踪机票但是该功能在这里没有用。从 GetTicket 返回时丢失了 Ticket ,而新的 Ticket 丢失了在 SaveTicket 中创建的。即使 ISession 处于请求级别并且能够看到发生的更改,NHibernate的更改跟踪功能也没有使用。

NHibernate have ability to track changes happen in Ticket but that ability is not useful here. Ticket is lost while returning from GetTicket and new Ticket is created while SaveTicket. Change tracking feature of NHibernate is not used at all even though ISession was at request level and was able to see the changes happen.

以下代码(绕过域模型)将正确跟踪更改:

Following code (which bypasses domain models) will track the changes properly though:

public Ticket GetTicket(int ticketId)
{
    return this.ticketsRepository.GetById(ticketId);
}

以下是如何获取和修改门票的方法

Following is how you get and modify Ticket:

Ticket ticket = applicationService.GetTicket(1);
ticket.Cost = .....
.....
.....

现在,您不调用 SaveTicket ;而是在应用程序中检测到EndOfRequest的某个地方 Flush ISession

Now, you do not call SaveTicket; instead you Flush the ISession somewhere in your application where you detect the EndOfRequest.

在这种情况下,NHibernate的更改跟踪将跟踪对 Ticket 所做的更改,并自动清除这些更改。

In this scenario, change tracking of NHibernate tracks the changes done to Ticket and flushes those automatically.

通过将持久性模型转换为域模型,我们将忽略NHibernate的这种功能,因为持久性模型永远不会改变。

By translating persistence model to domain model, we bypass this ability of NHibernate because persistence model is never changed.

每种方法的弊端。请参考问题。

There are benefits and drawbacks of each approach. Refer this question.

编辑:(对于您的 Update

Q1):如果修改了持久化模型的相同实例并且可见,则新代码将利用变更跟踪的优势到相同的 ISession 。在这种情况下,它还将利用会话级缓存。在使用AutoMapper进行映射时,如果不需要,NHibernate将加载引用的实体。但是,这取决于每个用例。

Q1): New code will take benefit of change tracking if same instance of persistence model is modified and visible to same ISession. It will also take benefit of Session Level Cache in that case. While mapping with AutoMapper, NHibernate will load referenced entities if any those may not be needed. This depends on each use-case though.

Q2):实际上,这应该是一个不同的问题,因为它太宽泛,无法在此答案中回答。无论如何,请参考

Q2): Actually this should be a different question being too broad to answer in this answer. Anyway, refer this.

这篇关于分离域模型和持久性模型时,如何跟踪变更问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆