DDD:如何处理“唯一性”业务逻辑

背景

唯一性约束是一个经常出现的业务逻辑,刚开始我觉得非常简单,不过深入考虑后,发现实现起来还不是那么简单,下面就让我们分析一下。

两种场景下的唯一性约束

第一种场景:聚合根的某个属性的唯一性约束

示例:用户的用户名必须唯一。

第一种实现思路:后验证+不用数据库索引,在插入用户名和修改用户名之后执行一次验证,这个验证逻辑执行的事务隔离级别必须处于“读未提交”级别。

 1 public volid Insert(User user)
 2 {
 3     using(var ts1 = new TransactionScope("读已提交"))
 4     {
 5         DoInsert(user);
 6         using(var ts2 = new TransactionScope("读未提交"))
 7         {
 8             //如果违背约束,抛出异常。
 9         }
10         ts1.Complete();
11     }
12 }

 第二种实现思路:前验证+不用数据库索引,在插入用户名和修改用户名之前执行一次验证,整个事务运行在“串行化”隔离级别。

1 public volid Insert(User user)
2 {
3     using(var ts = new TransactionScope("串行化"))
4     {            
5         //如果违背约束,抛出异常。
6         DoInsert(user);
7         ts.Complete();
8     }
9 }

 第三种实现思路:前验证+数据库索引,在插入用户名和修改用户名之前执行一次验证,整个事务运行在“读已提交”隔离级别。

1 public volid Insert(User user)
2  {
3      using(var ts = new TransactionScope("读已提交"))
4      {            
5          //如果违背约束,抛出异常。
6          DoInsert(user);
7          ts.Complete();
8      }
9  }

 第四实现思路种:内存锁。

有朋友会想,为啥不直接用数据库索引呢?失败了就跑出异常,因为我们需要收集到友好的异常信息显示给UI,所以才需要在程序里判定唯一性,然后抛出友好的异常信息。

总体来说我觉得第三种思路在现实中比较方便。

 

第二种场景:聚合内某个实体的属性的唯一性约束

示例:订单的订单项的产品必须唯一。

第一种实现思路:聚合根的乐观锁+聚合自身必须保证这种约束。

我觉得这个场景下只有这一种实现是比较合理的,就不介绍其他思路了。

备注

在健身房仓促写就,大家多提意见。

 

posted on 2013-06-15 21:14  幸福框架  阅读(2099)  评论(0编辑  收藏  举报

导航

我要啦免费统计