存储库应该是原子的吗?

时间:2016-12-12 13:42:03

标签: c# sql repository-pattern .net-core solid-principles

我正在设计我的存储库,我有一个疑问。例如,在创建新用户时,我必须在不同的表上添加条目。现在我用的是:

public User CreateNewUser()
{
    try
    {
        using (var con = new SqlConnection(_SecureConnectionString))
        {
            con.Open();

            using (var transaction = con.BeginTransaction())
            {
               User user = //User Repository query to INSERT the user on dbo.Users and return object

               user.Items = // Item Repository query to INSERT on dbo.Items that have a FK to dbo.Users
               user.Whatever = // Whatever repository call to INSERT on tables that are related to the new user

               transaction.Commit();
            }
        }
    catch (Exception ex)
    {
        transaction.Rollback();
        throw;
    }
}

我的问题是,如果创建一个新用户并且它总是必须在由其他存储库管理的不同表上创建条目,我应该避免这么原子化并在UserRepository上的单个查询上执行它,即使它插入到其他表上也是如此?我正在进行3次数据库命中,当时我可以在一次点击。

1 个答案:

答案 0 :(得分:0)

如果您依赖EF DbContext作为存储库,那么我对问题的回答是肯定的,您应该使用DbContext来插入所有新对象。这样,上下文将控制数据库事务,并且当您保存更改时,所有INSERT都将在单个事务中完成。

并且,正如您已经观察到的那样,这会导致轻微的并发症。除非您为整个模式或数据库构建一个巨大的上下文,否则某些实体将存在于多个DbContext中。

EF已经改进了对共享某些实体的上下文的支持,所以从语法的角度来看,你现在应该没问题。然后问题就是混乱,因为一个实体出现在多个上下文中。

我最近经常使用的另一种方法是应用DDD技术并将您的实体组织到定义良好的组中,命名为聚合。在这种情况下,一个实体将出现在一个上下文中。但是,在某些操作中,您必须使用多个上下文。这还需要您在上下文之间共享连接和事务,这些都为解决方案增加了很多复杂性。