【问题标题】:Should repositories be atomic?存储库应该是原子的吗?
【发布时间】:2016-12-12 13:42:03
【问题描述】:

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

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 次数据库命中。

【问题讨论】:

  • 你没有使用实体框架有什么原因吗?
  • 正如 Zoran 所说,这是游戏服务器解决方案的一部分,实体框架与 dapper 相比速度较差。对于这种特定情况(在注册时创建用户),我不需要很快,但并非总是如此。
  • 你缺少一个工作单元来协调跨存储库的事务。

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


【解决方案1】:

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

而且,正如您已经观察到的,这会导致轻微的复杂性。一些实体可能存在于多个DbContext 中,除非您正在为整个架构或数据库构建一个巨大的上下文。

EF 改进了对共享某些实体的上下文的支持,因此从句法的角度来看,您现在应该没问题。问题将是混乱,因为一个实体出现在多个上下文中。

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

【讨论】:

  • 感谢您的回复!,我正在开发一个内置于 .Net Core 的游戏服务器(这就是为什么我还没有 TransactionScope...;)),我决定选择 dapper由于查询速度性能。我不确定 dapper 是否可以做 EF 之类的上下文。
  • 不,使用 Dapper 您将构建自己的存储库。这使得在多个存储库中使用相同的实体变得更加容易,因为如何持久化它们是您的全部责任。
猜你喜欢
  • 1970-01-01
  • 2011-09-23
  • 2018-12-08
  • 2011-05-24
  • 2010-11-24
  • 1970-01-01
  • 2021-01-29
  • 1970-01-01
  • 2018-06-02
相关资源
最近更新 更多