【问题标题】:Using TransactionScope in Service Layer for UnitOfWork operations在服务层中使用 TransactionScope 进行 UnitOfWork 操作
【发布时间】:2014-02-28 16:48:07
【问题描述】:

将服务层的 TransactionScope 中的所有 3 个 dataprovider.GetXXX 方法捆绑为 UnitOfWork 的方法是否正确?

你会做一些不同的事情吗?

TransactionScpets 从哪里知道具体的 ConnectionString?

我应该从我的连接中获取 Transaction 对象并将这个 Transaction 对象传递给 TransactionScope 的构造函数吗?

像 AdministrationService.cs 这样的服务层

private List<Schoolclass> GetAdministrationData()
{

   List<Schoolclass> schoolclasses = null
   using (TransactionScope ts = new TransactionScope())
                    {
                        schoolclasses = _adminDataProvider.GetSchoolclasses();
                        foreach (var s in schoolclasses)
                        {
                           List<Pupil> pupils = _adminDataProvider.GetPupils(s.Id);
                           s.Pupils = pupils;

                           foreach (var p in pupils)
                           {
                               List<Document> documents = _documentDataProvider.GetDocuments(p.Id);
                               p.Documents = documents;
                           }
                        } 

                        ts.Complete();
                    }


   return schoolclasses;
}

举例说明 DataProvider 中这 3 种方法的外观:

public List<Schoolclass> GetSchoolclassList()
        {
            // used that formerly without TransactionSCOPE => using (var trans = DataAccess.ConnectionManager.BeginTransaction())
            using (var com = new SQLiteCommand(DataAccess.ConnectionManager))
            {
                com.CommandText = "SELECT * FROM SCHOOLCLASS";

                var schoolclasses = new List<Schoolclass>();

                using (var reader = com.ExecuteReader())
                {
                    Schoolclass schoolclass = null;
                    while (reader.Read())
                    {
                        schoolclass = new Schoolclass();
                        schoolclass.SchoolclassId = Convert.ToInt32(reader["schoolclassId"]);
                        schoolclass.SchoolclassCode = reader["schoolclasscode"].ToString();
                        schoolclasses.Add(schoolclass);
                    }
                }
                // Used that formerly without TransactionSCOPE => trans.Commit();
                return schoolclasses;
            }
        }

【问题讨论】:

  • TransactionScope 通常应该在进行数据修改或其他应该是“全有或全无”操作的操作(非数据库相关)时使用。从数据库中选择数据实际上不是一个事务。此外,如果您需要所有这些结果,您应该在一次对数据库的查询中获得多个结果集。在您的情况下,由于您没有使用存储过程,因此您应该在一个查询(CommandText)中有多个选择语句。然后,DataReader 将具有多个结果集,您可以使用 DbDataReader 的 NextResult() 方法对其进行迭代。
  • TransactionScope 使底层 ADO.NET 提供程序知道(反之亦然),因此您在 TransactionScope 的范围/生命周期内执行的任何操作都会自动参与事务。因此,它比经典的“connection.BeginTransaction()”api 更容易使用。
  • @Shiv 好的,我的样本在选择时有点愚蠢...用于更新、插入、删除其有效。是的,我知道数据读取器的 .NextResult() 方法,但有一件事我不能使用它。假设我在第一个 select 语句中获得了所有 Schoolclasses。您如何将结果集的 EACH schoolclassId 传递给第二个 select 语句,为 EACH SchoolclassId 获取学生?我不使用存储过程。我使用了一个简单的 Comment.Text = "Select .... fields from table"
  • 示例:com.CommandText = "从学校班级中选择 *;从学生中选择 *;从文档中选择 *";这是一个非常简单的示例,实际上我有一个从学生到文档的 N:M 关系...@Shiv 假设我在阅读器中有这 3 个结果集并做了 2 次 reader.NextResult() 我是对的,我仍然有比较 schoolclassId 和 student.schoolclassId 以了解哪个学生属于哪个 schoolclass.Pupils 集合?
  • @Shiv 结果集的坏处是我必须获取所有文档,因为在我使用 3 个 Select 语句构建查询的那一刻,我不知道与 PUPIL_DOCUMENT 相关的每个学生 ID再次引用 DOCUMENT 表的表。到目前为止,我可以看到没有适合我的 ResultSet。

标签: c# transactions transactionscope


【解决方案1】:

这看起来不错 - 这就是 TransactionScope 的用途,在您的代码中提供事务控制(这是 UoW 的常见模式)。

TransactionScpets 从哪里知道具体的 ConnectionString?

它没有。这取决于您的数据访问层,对TransactionScope 并没有太大意义。 TransactionScope 所做的是创建一个事务(默认情况下将是一个轻量级事务) - 如果您的数据访问跨越多个数据库,该事务将自动升级为分布式事务。它在后台使用 MSDTC。

我应该从我的连接中获取 Transaction 对象并将这个 Transaction 对象传递给 TransactionScope 的构造函数吗?

不,不,不。见上文。做你现在正在做的事。嵌套TransactionScopes 没有坏处。

【讨论】:

  • ok Oded,但我不访问多个数据库,只是在多个表上进行更新/删除/插入 - 好的,我知道我在这里做了一个选择......但现在忘记了 ;-) -
  • @msfanboy - 不是重点。您可以以与单个数据库相同的方式使用它。我的答案是……
  • @Oded 所以 TransactionScope 类也使我免于执行业务层保存/存储方法,我总是有一个事务参数对吗?实际上是的很好,所以那堂课很好,呵呵。
猜你喜欢
  • 2017-01-07
  • 1970-01-01
  • 2017-04-10
  • 2018-01-04
  • 1970-01-01
  • 2016-09-16
  • 2018-05-24
  • 2011-07-18
  • 2023-03-20
相关资源
最近更新 更多