gpt4 book ai didi

c# - Nhibernate:谁负责非 web 应用程序中的事务管理

转载 作者:太空狗 更新时间:2023-10-29 19:41:45 27 4
gpt4 key购买 nike

在 Web 应用程序中,一个工作单元负责事务管理。

但是 Windows 应用程序呢?

据我所知,存储库是我的数据访问层和业务层之间的连接器。它从我的业务层隐藏了所有数据访问内容。

使用这个事实让我想到将所有事务内容放入存储库中。

但我读到在存储库上使用 Commit/RollBack 方法违反了存储库的意图。

我问自己谁负责非 Web 应用程序中的事务管理,以及如何从业务层隐藏事务/Nhibernate 内容?

最佳答案

一般的回答是“谁实例化 ISession 就应该处理掉它。如果事务还没有提交,这实际上是回滚。”

我已经成功地使用命令模式来定义我想对工作单元执行的操作。假设我们有一个 Person实体,我们可以做的事情之一就是更改一个人的名字。让我们从实体开始:

public class Person
{
public virtual int Id { get; private set; }
public virtual string Name { get; private set; }

public virtual void ChangeName(string newName)
{
if (string.IsNullOrWhiteSpace(newName))
{
throw new DomainException("Name cannot be empty");
}

if (newName.Length > 20)
{
throw new DomainException("Name cannot exceed 20 characters");
}

this.Name = newName;
}
}

像这样定义一个简单的 POCO 命令:

public class ChangeNameCommand : IDomainCommand
{
public ChangeNameCommand(int personId, string newName)
{
this.PersonId = personId;
this.NewName = newName;
}

public int PersonId { get; set; }
public string NewName { get; set; }
}

...和命令的处理程序:

public class ChangeNameCommandHandler : IHandle<ChangeNameCommand>
{
ISession session;

public ChangeNameCommandHandler(ISession session)
{
// You could demand an IPersonRepository instead of using the session directly.
this.session = session;
}

public void Handle(ChangeNameCommand command)
{
var person = session.Load<Person>(command.PersonId);
person.ChangeName(command.NewName);
}
}

目标是存在于 Session/Work 范围之外的代码可以做这样的事情:

public class SomeClass
{
ICommandInvoker invoker;

public SomeClass(ICommandInvoker invoker)
{
this.invoker = invoker;
}

public void DoSomething()
{
var command = new ChangeNameCommand(1, "asdf");
invoker.Invoke(command);
}
}

命令的调用意味着“在一个工作单元上执行此命令”。这是我们希望在调用命令时发生的情况:

  1. 开始一个 IoC 嵌套范围(“工作单元”范围)
  2. 开始一个 ISession 和 Transaction(这可能是第 3 步的一部分)
  3. 解决 IHandle<ChangeNameCommand>来自 IoC 范围
  4. 将命令传递给处理程序(域执行其工作)
  5. 提交交易
  6. 结束 IoC 范围(工作单元)

所以这是一个使用 Autofac 的例子作为 IoC 容器:

public class UnitOfWorkInvoker : ICommandInvoker
{
Autofac.ILifetimeScope scope;

public UnitOfWorkInvoker(Autofac.ILifetimeScope scope)
{
this.scope = scope;
}

public void Invoke<TCommand>(TCommand command) where TCommand : IDomainCommand
{
using (var workScope = scope.BeginLifetimeScope("UnitOfWork")) // step 1
{
var handler = workScope.Resolve<IHandle<TCommand>>(); // step 3 (implies step 2)
handler.Handle(command); // step 4

var session = workScope.Resolve<NHibernate.ISession>();
session.Transaction.Commit(); // step 5

} // step 6 - When the "workScope" is disposed, Autofac will dispose the ISession.
// If an exception was thrown before the commit, the transaction is rolled back.
}
}

注意:UnitOfWorkInvoker我在这里展示的违反了SRP - 这是一个 UnitOfWorkFactory , 一个 UnitOfWork , 和一个 Invoker一体。在我的实际实现中,我将它们分解。

关于c# - Nhibernate:谁负责非 web 应用程序中的事务管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6835795/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com