entity-framework - DDD : Adding entity to repository and handlig exceptions

标签 entity-framework exception repository domain-driven-design logic

我正在尝试使用 DDD 来建模一个简单的域。数据库层使用Entity Framework实现,领域对象为POCO。域具有用户实体,该实体具有 FirstName、LastName 和 Username 属性。因此,域定义了为用户处理存储库的 IRepository。

现在,域逻辑中的一项要求是不能存在两个具有相同用户名的用户。因此,当另一个具有相同用户名的用户已存在时尝试添加新用户应该会引发异常。

IUnitOfWork unitOfWork = new UnitOfWork();
IRepository<User> users = unitOfWork.Users;

User user1 = new User() { Username = "jsmith", FirstName = "John", LastName = "Smith" };
users.Add(user1);   
users.Save();       // ok, new user added to the underlying database

User user2 = new User() { Username = "jsmith", FirstName = "Jim", LastName = "Smith" };
users.Add(user2); // exception here?
users.Save();     // or exception here?

这是应进入添加新用户的 WPF 应用程序的代码示例。这里,UnitOfWork封装了Entity Framework的DbContext对象。

我的问题是我应该如何以及在哪里强制执行此域规则?尝试将用户添加到存储库时或者调用 Save() 方法时是否应该引发异常?我是否应该创建域服务来添加新用户,然后在那里处理所有域逻辑规则?

另外,我应该抛出什么异常?我应该创建一些自定义域异常,例如 DuplicateUserException 或类似的东西吗?

最佳答案

数据库是该规则的最终执行者。现在,这是一个多用户应用程序吗?如果是这样,那么最务实的方法是依赖 db ,捕获 sql 异常,然后抛出一个业务规则异常,该异常将被重定向到 UI(即会触发错误消息)。

您可以验证域级别是否已存在名称(通过服务是最有效的方法),但这在并发环境中可能会失败。然而,对于单用户应用程序来说,它是一个优雅而干净的解决方案。对于单用户应用程序,我的意思是所有应用程序一次都会为一个用户提供服务。如果您有 WPF 客户端和 Web 服务,那就是多用户应用程序。

最好的选择是让持久性(在本例中是数据库)处理此规则,因为存储库有责任确保不存在重复名称(存储库不是哑桶,它是持久性的管理器)并且它也解决了并发问题。

请注意,我没有提到 EF,因为与数据库通信的方式并不重要。如果明天您将切换到 Azure db,解决方案仍然相同,只是实现的特定部分会有所不同。

关于entity-framework - DDD : Adding entity to repository and handlig exceptions,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11181396/

相关文章:

c# - 使用 Dapper QueryAsync 返回单个对象

c# - 模型类中的 EF 上下文

c# - DbContext 可以组合而不是继承吗?

.net - MEF ComposeParts。如何处理插件异常

c++ - 未处理的异常 : 0x80000001: Not implemented. (VC++)

asp.net - 使用 ELMAH 记录 WCF 服务的异常

c# - 带有 MySQL 的 ASP.NET MVC EF 需要 .dll 及其用法?

c# - .AsNoTracking() 有什么区别?

git - 当我在 master 上使用 BFG Repo-Cleaner 时,其他分支会发生什么

具有接口(interface)的 C# MVC 通用存储库类