使用 TransactionScope 实现 SqlServer 的分布式事务

本来是想通过 TransactionScope 来实现分布式事务的。

ORM 使用的是 FluentData

测试代码

using (var ts = new TransactionScope())
{
    using (var db_wirte = new DbContext().ConnectionString(CONN_WRITE, new SqlServerProvider()).UseTransaction(true))
    {
        db_wirte.Insert("Table_A", new TestModel() {
            Guid = Guid.NewGuid(),
            Name = "测试数据",
            CreateTime = DateTime.Now,
            ModifyTime = DateTime.Now,
        }).AutoMap().Execute();

        using (var db_prod = new DbContext().ConnectionString(CONN_PROD, new SqlServerProvider()).UseTransaction(true))
        {
            db_prod.Insert("Table_B", new TestModel()
            {
                Guid = Guid.NewGuid(),
                Name = "测试数据",
                CreateTime = DateTime.Now,
                ModifyTime = DateTime.Now,
            }).AutoMap().Execute();

            db_prod.Commit();
        }

        db_wirte.Commit();
    }

    ts.Complete();
}
.NET Timeout expired

定时任务中经常出现 Timeout 异常。数据库是 SqlServer,DAO 使用的 FluentData

.NET Core 中的异常信息:

System.Data.SqlClient.SqlException (0x80131904): Timeout 时间已到。在操作完成之前超时时间已过或服务器未响应。 ---> System.ComponentModel.Win32Exception (0x80004005): 等待的操作过时。
   在 Framework.Data.ExecuteQueryHandler.HandleQueryException(Exception exception)
   在 Framework.Data.ExecuteQueryHandler.ExecuteQuery(Boolean useReader, Action action)
   在 Framework.Data.DbCommand.QueryMany[TEntity,TList](Action`2 customMapper)
   在 Framework.Data.DbCommand.QueryMany[TEntity](Action`2 customMapper)
FluentData 中使用临时表

最近又开始做了一部分系统慢接口的优化,有个 SQL 优化时需要使用到临时表。要先创建一个临时表并插入数据,然后在之后的查询中使用。

由于项目中 ORM 框架使用的是 FluentData,需要通过特定的写法才能实现上述效果。 FluentData 是一个轻量级的 ORM 框架,性能还是比较高的。

如果使用 DbContext 的默认设置执行 SQL,后面的查询中会报找不到临时表的异常。这个是由于 FluentData 默认设置每次查询是要创建一个新连接的(由于 SqlConnection 默认是开启连接池的,这样做本身并没有什么问题),这就导致创建临时表的会话和后面使用临时表的会话并不是同一个会话,而 #t 临时表只能在当前会话中访问,所以就发生了异常。

FluentData 使用 using 形式的事务时,事务结束后自动关闭事务标志

FluentData 中的事务开启格式如下:

using (var db = DbContext.UseTransaction(true))
{

}
FluentData Error: Could not map

查询后生成对应的模型时出现 Could not map 的错。

原因是查询关联了 2 张表,查询字段里直接写了 select * 导致的。
查询的字段过多,模型中没有对应的属性,导致绑定时出错。

修改为 select tablename.* 后就对了.

注意

如果几张表中有重复的字段,后面的字段值应该会覆盖前面的值.

微型 ORM-FluentData

简介

与其他微型 ORM(如 Dapper 和 Massive)类似,FluentData 关注性能和易用性。它允许开发人员拥有对 SQL 较多的控制,而不是依赖 ORM 进行自动生成。它不仅可以使用 SQL 来执行查询、增添和更新操作,还可以支持使用存储过程和事务。 根据文档描述,FluentData 可以在不改动已有结构的情况下,与任何业务对象一同工作。

以下是 FluentData 的一些其他特性:

  • 多结果集(Multiple Result Set):在一次数据库操作下返回多个数据集;

  • 开发人员可使用强类型对象或动态对象;

  • 可为创建时需要特殊处理的复杂对象自定义实体工厂(Custom Entity Factory);

  • 具有添加其他数据库支持的能力。

FluentData 如何实现分页查询?

自己在 SQL 文中使用 TOP 也可以实现, FluentData 中的 SelectBuilder 类提供了 Paging 方法有同样的功能。

示例:

DataTable dt = dbContext.Select<DataTable>(field).From(from).Where(where).Parameters(paramList).GroupBy(groupby).OrderBy(orderby).Paging(pageIndex, pageSize).QuerySingle();
FluentData 如何给 in 中的参数赋值?

SQL 文中 IN 的写法:

in(@Guids)