C# Dapper.NET连接/查询最佳实践

C# Dapper.NET连接/查询最佳实践,c#,asp.net,.net,sql-server,dapper,C#,Asp.net,.net,Sql Server,Dapper,所以我读了一大堆的链接/问题,但我仍然不能得到一个明确的答案 在ASP.NET应用程序中使用Dapper执行SQL查询时,打开/关闭连接的最佳做法是什么 以下是我目前遵循的模式: using (var db = new SqlConnection(_connectionString)) { return db.Query("dbo.SomeQuery"); } 基本上,每次都可以根据需要打开/关闭SQL连接 根据我的理解,上述代码应该自动打开/关闭SQL连接(例如,我不需要明确地执行d

所以我读了一大堆的链接/问题,但我仍然不能得到一个明确的答案

在ASP.NET应用程序中使用Dapper执行SQL查询时,打开/关闭连接的最佳做法是什么

以下是我目前遵循的模式:

using (var db = new SqlConnection(_connectionString))
{
    return db.Query("dbo.SomeQuery");
}
基本上,每次都可以根据需要打开/关闭SQL连接

根据我的理解,上述代码应该自动打开/关闭SQL连接(例如,我不需要明确地执行
db.open
db.close

我看到的问题是,过了一段时间,我发现了一大堆错误:

InvalidOperationExceptionTimeout已过期。超时时间已过 在从池中获取连接之前。这可能已经发生了 因为所有池连接都在使用中,并且最大池大小为 达到

在这段时间内,我有一个SQL事件探查器跟踪,我没有看到任何会阻止任何内容的长查询,因此我的ASP.NET web应用程序似乎正在耗尽连接(而不是花费太长的时间来执行查询)

有人能告诉我我做错了什么吗


旁注:我的应用程序是作为Azure Web应用程序运行的,因此很遗憾,我无法看到Web应用程序实际打开了多少个连接:(

根据我的意见,使用声明关闭连接,但您明确告诉我打开一个连接,如下所示:

using (var db = new SqlConnection(_connectionString))

{
       db.open();

    return db.Query("dbo.SomeQuery");
}

使用block将处理资源管理,因此您不需要手动关闭连接,此外,手动关闭连接将阻止连接池并降低您的性能。

根据我在这一类似经历中的经验,超时可能是由于SQL连接超时。这可能是因为,假设SQL server在X core server上运行,并且并发调用使用了所有可能的最大连接数,后续调用将进入等待模式。如果未指定,则采用默认连接超时


您可能希望在连接字符串或数据恢复层中覆盖该属性。请检查ConnectionTimeout属性。

在我看来,您的代码很好,Dapper将打开和关闭集合本身,但出现的异常是,连接池在超时时没有可返回的可用连接。其原因可能是这些:

  • 您的查询是长期运行的
  • 您的连接池大小对于您需要的用户负载来说很小 have(默认值为100)
  • 1和2的混合
  • 所以,根据需要调整连接池大小,并调整查询和数据库本身。或者使用更大的连接超时


    PS:当您手动关闭连接时,连接池实际上不会关闭它,因为打开和关闭数据库连接的成本很高,所以让Dapper打开和关闭连接本身没有问题。

    下面是一个在内部使用Dapper的数据库上下文示例,我认为这些都是好的最佳实践。我为一个项目整合了这些实践,它有发展,有来自不同地方的最佳想法,还有我自己的一些经验/投入。本文还列举了不同类型的数据库操作:

    • 标量
    • 列表
    • 单一实体
    • 删除
    • 更新
    • 动态查询构建
    • 获取新插入的记录ID
    • 使用SqlMapper.GridReader处理多个结果集
    此外,该模式还用于注入设置/连接字符串信息,与Dapper无关,但由于Dapper在.NET应用程序中大量使用,因此仍然可以方便地查看

    我引入了一个代码风格的概念,即将包含原始数据的类称为“实体”,将为调用者清理的转换数据称为“模型”。“视图模型”用于堆栈中的前端。有时上下文会将模型返回给调用方,有时会返回原始实体,因为调用方需要原始实体进行比上下文应该负责的更深入的转换。这个概念可能并不完美,在某些方面我是自己编造的,因为我发现“模型”一词在不同的堆栈、团队和公司中有很多含义。我们为世界建模,数据库可以被称为模型,实体可以被视为模型……总之,这是一门艺术,也是一门科学。我在下面的代码中试图更好地解释返回类型。:)

    使用系统;
    使用System.Collections.Generic;
    使用系统数据;
    使用System.Data.SqlClient;
    使用System.Linq;
    使用整洁;
    使用Microsoft.Extensions.Options;
    使用Tsl.CustomPrice.Interface;
    使用Tsl.CustomPrice.Model;
    使用Tsl.CustomPrice.Model.Configuration;
    使用Tsl.CustomPrice.Model.Tso;
    使用Tsl.Shared.Enumeration;
    命名空间Tsl.CustomPrice.Data
    {
    公共类TsoContext:ITsoContext
    {
    私有只读字符串_connectionString;
    私有IDbConnection=>newSQLConnection(_connectionString);
    公共TsoContext(IOptions设置)
    {
    _connectionString=settings.Value.connectionString.TsoConnection;
    }
    #区域自定义价格列
    public int GetCustomPriceColumnCountForUser(int userId)
    {
    使用(IDbConnection conn=连接)
    {
    变量查询=@“选择计数(*)
    来自[TSO].[dbo].[CustomPriceColumn](NOLOCK)
    其中[EntityID]=@userId和[EntityTypeID]=1——用户”;
    返回conn.ExecuteScalar(查询,新{userId});
    }
    }
    公共CustomPriceColumnModel GetLastUpdatedCustomPriceColumn(int userId)
    {
    使用(IDbConnection conn=连接)
    {
    var query=@“选择[CustomPriceColumnID]
    ,[EntityID]
    从…起
    
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.SqlClient;
    using System.Linq;
    using Dapper;
    using Microsoft.Extensions.Options;
    using Tsl.CustomPrice.Interfaces;
    using Tsl.CustomPrice.Model;
    using Tsl.CustomPrice.Model.Configuration;
    using Tsl.CustomPrice.Model.Tso;
    using Tsl.Shared.Enumeration;
    
    namespace Tsl.CustomPrice.Data
    {
        public class TsoContext : ITsoContext
        {
            private readonly string _connectionString;
            private IDbConnection Connection => new SqlConnection(_connectionString);
    
            public TsoContext(IOptions<DbSettings> settings)
            {
                _connectionString = settings.Value.ConnectionStrings.TsoConnection;
            }
    
            #region Custom Price Column
    
            public int GetCustomPriceColumnCountForUser(int userId)
            {
                using (IDbConnection conn = Connection)
                {
                    var query = @"SELECT count(*)
                                FROM [TSO].[dbo].[CustomPriceColumn] (NOLOCK)
                                WHERE [EntityID] = @userId and [EntityTypeID] = 1 --User";
    
                    return conn.ExecuteScalar<int>(query, new { userId });
                }
            }
    
            public CustomPriceColumnModel GetLastUpdatedCustomPriceColumn(int userId)
            {
                using (IDbConnection conn = Connection)
                {
                    var query = @"SELECT [CustomPriceColumnID]
                                  ,[EntityID]
                              FROM [TSO].[dbo].[CustomPriceColumn] (NOLOCK)
                                WHERE [EntityID] = @userId and [EntityTypeID] = 1 --User
                                ORDER BY [LastUpdatedDateTime] desc";
    
                    return conn.Query<CustomPriceColumnModel>(query, new { userId }).FirstOrDefault();
                }
            }
    
            public CustomPriceColumnModel GetCustomPriceColumn(int customPriceColumnId, int userId)
            {
                using (IDbConnection conn = Connection)
                {
                    const string query = @"SELECT [CustomPriceColumnID]
                              ,[EntityID]
                              ,[EntityTypeID]
                              ,[CustomPriceColumnTypeID]
                              ,a.[CreatedDateTime]
                              ,case when (CreatedByUserID = @userId or CustomPriceColumnTypeID = 2) then 1 else 0 end as IsEditable
                              ,b.FirstName as CreatedByFirstName
                              ,b.LastName as CreatedByLastName
                          FROM [dbo].[CustomPriceColumn] a (nolock)
                          left join [User] b on b.UserID = a.CreatedByUserID
                          WHERE [CustomPriceColumnID] = @customPriceColumnId";
    
                    return conn.QueryFirstOrDefault<CustomPriceColumnModel>(query, new { @customPriceColumnId=customPriceColumnId, @userId=userId });
                }
            }
            public IEnumerable<CustomPriceColumnModel> GetCustomPriceColumns(int userId)
            {
                using (IDbConnection conn = Connection)
                {
                    const string query = @"SELECT
                                  [CustomPriceColumnID]
                                  ,[EntityID]
                                  ,[EntityTypeID]
                                  ,case when (CreatedByUserID = @userId or CustomPriceColumnTypeID = 2) then 1 else 0 end as IsEditable
                                  ,b.FirstName as CreatedByFirstName
                                  ,b.LastName as CreatedByLastName
                                FROM CustomPriceColumn cpc (nolock)
                                    inner join [User] u (nolock)
                                        on u.UserID = @userId
                                    left join [User] b on b.UserID = CreatedByUserID
                                WHERE (EntityID = @userId and EntityTypeID = 1)
                                    or (CreatedByUserID = @userId)
                                    or (EntityID = u.CompanyID and EntityTypeID = 0)";
    
                    return conn.Query<CustomPriceColumnModel>(query, new { userId });
                }
            }
    
    
            public int CreateCustomPriceColumn(string customPriceColumnName, string customPriceColumnDescription, int entityId, int createdByUserId, string countryCode, IndustryTypes industryTypeId, EntityTypes entityTypeId, CustomPriceColumnTypes customPriceColumnTypeId, string systemUserName, string actorName)
            {
                using (IDbConnection conn = Connection)
                {
                    var query = @"INSERT INTO [TSO].[dbo].[CustomPriceColumn]
                                           ([EntityID]
                                           ,[EntityTypeID]
                                           ,[CustomPriceColumnTypeID]
                                           ,[CreatedByUserID]
                                           ,[IndustryTypeID]
                                           ,[CountryCode]
                                           ,[CustomPriceColumnName]
                                           ,[CustomPriceColumnDescription]
                                           ,[CreatedDateTime]
                                           ,[LastUpdatedDateTime]
                                           ,[ActorName]
                                           ,[SystemUserName])
                                     VALUES
                                           (@entityId
                                           ,@entityTypeId
                                           ,@customPriceColumnTypeId
                                           ,@createdByUserId
                                           ,@industryTypeId
                                           ,@countryCode
                                           ,@customPriceColumnName
                                           ,@customPriceColumnDescription
                                           ,getdate()
                                           ,getdate()
                                           ,@actorName
                                           ,@systemUserName);
                                        SELECT CAST(SCOPE_IDENTITY() as int)";
    
    
                    return conn.ExecuteScalar<int>(query,
                        new
                        {
                            entityId,
                            entityTypeId,
                            customPriceColumnTypeId,
                            createdByUserId,
                            industryTypeId,
                            countryCode,
                            customPriceColumnName,
                            customPriceColumnDescription,
                            actorName,
                            systemUserName
                        });
    
                }
            }
    
            public void UpdateCustomPriceColumn(int customPriceColumnId, string customPriceColumnName, string customPriceColumnDescription, int entityId, IndustryTypes industryTypeId, EntityTypes entityTypeId, CustomPriceColumnTypes customPriceColumnTypeId, string systemUserName, string actorName)
            {
                using (IDbConnection conn = Connection)
                {
                    var query = @"UPDATE [TSO].[dbo].[CustomPriceColumn]
                               SET [EntityID] = @entityId
                                  ,[EntityTypeID] = @entityTypeId
                                  ,[CustomPriceColumnTypeID] = @customPriceColumnTypeId
                                  ,[IndustryTypeID] = @industryTypeId
                                  ,[CustomPriceColumnName] = @customPriceColumnName
                                  ,[CustomPriceColumnDescription] = @customPriceColumnDescription
                                  ,[LastUpdatedDateTime] = getdate()
                             WHERE [CustomPriceColumnID] = @customPriceColumnId";
    
    
                    conn.Execute(query,
                        new
                        {
                            customPriceColumnId,
                            entityId,
                            entityTypeId,
                            customPriceColumnTypeId,
                            industryTypeId,
                            customPriceColumnName,
                            customPriceColumnDescription,
                            actorName,
                            systemUserName
                        });
    
                }
            }
    
            public void DeleteCustomPriceColumn(int customPriceColumnId)
            {
                using (IDbConnection conn = Connection)
                {
                    var query = @"DELETE FROM [TSO].[dbo].[CustomPriceColumn]
                                 WHERE [CustomPriceColumnID] = @customPriceColumnId";
    
    
                    conn.Execute(query,
                        new
                        {
                            customPriceColumnId
                        });
    
                }
            }
    
            public CustomPriceColumnMetaDataForCpfExportEntity GetCustomPriceColumnMetaDataForCpfExport(int customPriceColumnId)
            {
                var ret = new CustomPriceColumnMetaDataForCpfExportEntity();
                using (IDbConnection conn = Connection)
                {
                    const string query = @"
                        -- TOTAL RULES VS. TOTAL PERCENT RULES
                        SELECT tr.TotalRules, trp.TotalPercentRules FROM
                        (SELECT CustomPriceColumnId, COUNT(*) AS TotalRules FROM tso.dbo.CustomPriceRule WHERE CustomPriceColumnID = @CustomPriceColumnId GROUP BY CustomPriceColumnID) as tr
                        JOIN
                        (SELECT CustomPriceColumnId, COUNT(*) AS TotalPercentRules FROM tso.dbo.CustomPriceRule WHERE CustomPriceColumnID = @CustomPriceColumnId AND IsPercent = 1 GROUP BY CustomPriceColumnID) AS trp
                        ON tr.CustomPriceColumnID = trp.CustomPriceColumnID;
                        -- TOTAL RULES BY BASE COLUMN
                        SELECT BaseColumnPriceTypeID, OperationTypeId, COUNT(*) AS TotalRules FROM tso.dbo.CustomPriceRule WHERE CustomPriceColumnID = @CustomPriceColumnId
                        GROUP BY BaseColumnPriceTypeID, OperationTypeId";
    
                    using (SqlMapper.GridReader multi = conn.QueryMultiple(query, new { @customPriceColumnId = customPriceColumnId }))
                    {
                        ret.MetaData = multi.Read<CustomPriceColumnMetaDataEntity>().SingleOrDefault();
                        ret.BasePriceColumnRuleCounts = multi.Read<BasePriceColumnRuleCountEntity>().ToList();
                    }
    
                    return ret;
                }
            }
            #endregion
    
            #region Custom Price Rule
    
            public IEnumerable<int> GetCustomPriceRulesIds(int customPriceColumnId)
            {
    
                using (IDbConnection conn = Connection)
                {
                    var query =
                        @"SELECT [CustomPriceRuleId] FROM [dbo].[CustomPriceRule] (nolock) WHERE [CustomPriceColumnId] = @customPriceColumnId";
    
                    return conn.Query<int>(query, new {customPriceColumnId});
                }
    
            }
    
            public IEnumerable<CustomPriceRuleModel> GetCustomPriceRules(int customPriceColumnId, int index, int pageSize)
            {
                //implementation can be extended to allow sorting by other 
                var sortBy = "a.CreatedDateTime desc";
    
                using (IDbConnection conn = Connection)
                {
                    var query = @"SELECT  *
                                FROM     
                                    (SELECT ROW_NUMBER() OVER ( ORDER BY {0}) AS RowNum,  
                                        COUNT(*) OVER () AS TotalRows, 
                                        [CustomPriceRuleId] 
                                        FROM [dbo].[CustomPriceRule] a (nolock) 
                                            left outer join [dbo].[Commodity] b (nolock) on a.CommodityId = b.CommodityID 
                                            left outer join [dbo].[Company] c (nolock) on a.ManufacturerCompanyId = c.CompanyId 
                                            left outer join [dbo].[Item] d (nolock) on a.ItemId = d.ItemID 
                                        WHERE [CustomPriceColumnId] = @customPriceColumnId 
                                      ) AS result 
                                WHERE RowNum BETWEEN ( ((@index - 1) * @pageSize )+ 1) AND @index*@pageSize 
                                            ORDER BY RowNum";
    
                    query = string.Format(query, sortBy);
    
                    return conn.Query<CustomPriceRuleModel>(query, new { customPriceColumnId, index, pageSize });
                }
            }
    
            public CustomPriceRuleModel GetCustomPriceRule(int customPriceRuleId)
            {
                using (IDbConnection conn = Connection)
                {
                    const string query = @"SELECT [CustomPriceRuleId]
                                          ,[CustomPriceColumnId]
                                      FROM [TSO].[dbo].[CustomPriceRule]
                                      WHERE [CustomPriceRuleId] = @customPriceRuleId";
    
                    return conn.QueryFirstOrDefault<CustomPriceRuleModel>(query, new { customPriceRuleId });
                }
            }
    
            public CustomPriceRuleModel GetCustomPriceRuleByItemId(int customPriceColumnId, int itemId)
            {
                using (IDbConnection conn = Connection)
                {
                    const string query = @"SELECT [CustomPriceRuleId]
                                          ,[CustomPriceColumnId]
                                          ,[CustomPriceRuleLevelId]
                                      FROM [TSO].[dbo].[CustomPriceRule]
                                      WHERE [CustomPriceColumnId] = @customPriceColumnId and [ItemId] = @itemId";
    
                    return conn.QueryFirstOrDefault<CustomPriceRuleModel>(query, new { customPriceColumnId, itemId });
                }
            }
    
            public CustomPriceRuleModel FindCustomPriceRule(int customPriceColumnId, CustomPriceRuleLevels customPriceRuleLevel,
                    int? itemId, int? manufacturerCompanyId, int? commodityId, string ucc)
            {
                using (IDbConnection conn = Connection)
                {
                    string query = @"SELECT [CustomPriceRuleId]
                                          ,[CustomPriceColumnId]
                                          ,[UCC]
                                      FROM [TSO].[dbo].[CustomPriceRule]
                                      WHERE [CustomPriceColumnId] = @customPriceColumnId
                                      AND [CustomPriceRuleLevelId] = @customPriceRuleLevel";
                    var parameters = new DynamicParameters();
                    parameters.Add("@customPriceColumnId", customPriceColumnId);
                    parameters.Add("@customPriceRuleLevel", (int)customPriceRuleLevel);
    
                    switch (customPriceRuleLevel)
                    {
                        case (CustomPriceRuleLevels.Item):
                            query += @" AND ItemId = @itemId";
                            parameters.Add("@itemId", itemId);
                            break;
                        case (CustomPriceRuleLevels.ManufacturerAndCommodity):
                            query += @" AND ManufacturerCompanyID = @manufacturerCompanyId
                                AND CommodityId = @commodityId";
                            parameters.Add("@manufacturerCompanyId", manufacturerCompanyId);
                            parameters.Add("@commodityId", commodityId);
                           break;
                        case (CustomPriceRuleLevels.Manufacturer):
                            query += @" AND ManufacturerCompanyID = @manufacturerCompanyId";
                            parameters.Add("@manufacturerCompanyId", manufacturerCompanyId);
                            break;
                        case (CustomPriceRuleLevels.Commodity):
                            query += @" AND CommodityId = @commodityId";
                            parameters.Add("@commodityId", commodityId);
                            break;
                        case (CustomPriceRuleLevels.Ucc):
                            query += @" AND ManufacturerCompanyID = @manufacturerCompanyId
                                AND Ucc = @ucc";
                            parameters.Add("@manufacturerCompanyId", manufacturerCompanyId);
                            parameters.Add("@ucc", ucc);
                            break;
                    }
    
                    return conn.QueryFirstOrDefault<CustomPriceRuleModel>(query, parameters);
                }
            }
    
            public void UpdateCustomPriceRule(int customPriceRuleId, CustomPriceRuleLevels customPriceRuleLevel, int? itemId, int? manufactuerCompanyId,
                int? commodityId, PriceTypes? baseColumnPriceTypeId, CustomPriceOperations? operationTypeId, decimal customPriceRuleValue, bool isPercent, string customPriceRuleDescription,
                Uom? fixedPriceUnitIfMeasureTypeCode, string ucc, string actorName, string systemUsername)
            {
    
                using (IDbConnection conn = Connection)
                {
                    var query = @"UPDATE [TSO].[dbo].[CustomPriceRule]
                                   SET [CustomPriceRuleLevelId] = @customPriceRuleLevel
                                      ,[ItemId] = @itemId
                                      ,[ManufacturerCompanyId] = @manufactuerCompanyId
                                      ,[CommodityId] = @commodityId
                                      ,[BaseColumnPriceTypeId] = @baseColumnPriceTypeId
                                      ,[OperationTypeId] = @operationTypeId
                                      ,[CustomPriceRuleValue] = @customPriceRuleValue
                                      ,[IsPercent] = @isPercent
                                      ,[CustomPriceRuleDescription] = @customPriceRuleDescription
                                      ,[FixedPriceUnitOfMeasureTypeCode] = @strUom
                                      ,[LastUpdatedDateTime] = getdate()
                                      ,[ActorName] = @actorName
                                      ,[SystemUsername] = @systemUsername
                                      ,[UCC] = @ucc
                                 WHERE [CustomPriceRuleId] = @customPriceRuleId";
    
                    var strUom = fixedPriceUnitIfMeasureTypeCode != null ? fixedPriceUnitIfMeasureTypeCode.ToString() : null;
                    // HACK: See TSL-1235 : CustomPriceOperations.FixedPrice must translate to a null in the CustomPriceRule row.
                    CustomPriceOperations? opTypeId = operationTypeId == CustomPriceOperations.FixedPrice ? null : operationTypeId;
    
                    conn.Execute(query,
                        new
                        {
                            customPriceRuleId,
                            customPriceRuleLevel,
                            itemId,
                            manufactuerCompanyId,
                            commodityId,
                            baseColumnPriceTypeId,
                            operationTypeId = opTypeId,
                            customPriceRuleValue,
                            isPercent,
                            customPriceRuleDescription,
                            strUom,
                            ucc,
                            actorName,
                            systemUsername
                        });
    
                }
            }
    
    
    
            public int CreateCustomPriceRule(int customPriceColumnId, CustomPriceRuleLevels customPriceRuleLevel, int? itemId,
            int? manufactuerCompanyId, int? commodityId, PriceTypes? baseColumnPriceTypeId, CustomPriceOperations? operationTypeId,
            decimal customPriceRuleValue, bool isPercent, string customPriceRuleDescription, Uom? fixedPriceUnitIfMeasureTypeCode,
            string ucc, string actorName, string systemUsername)
            {
                using (IDbConnection conn = Connection)
                {
                    var query = @"INSERT INTO [TSO].[dbo].[CustomPriceRule]
                                   ([CustomPriceColumnId]
                                   ,[CustomPriceRuleLevelId]
                                   ,[ItemId]
                                   ,[ManufacturerCompanyId]
                                   ,[CommodityId]
                                   ,[BaseColumnPriceTypeId]
                                   ,[OperationTypeId]
                                   ,[CustomPriceRuleValue]
                                   ,[IsPercent]
                                   ,[CustomPriceRuleDescription]
                                   ,[FixedPriceUnitOfMeasureTypeCode]
                                   ,[CreatedDateTime]
                                   ,[LastUpdatedDateTime]
                                   ,[ActorName]
                                   ,[SystemUsername]
                                   ,[UCC])
                             VALUES
                                   (@customPriceColumnId
                                   ,@customPriceRuleLevel
                                   ,@itemId
                                   ,@manufactuerCompanyId
                                   ,@commodityId
                                   ,@baseColumnPriceTypeId
                                   ,@operationTypeId
                                   ,@customPriceRuleValue
                                   ,@isPercent
                                   ,@customPriceRuleDescription
                                   ,@strUom
                                   ,getdate()
                                   ,getdate()
                                   ,@actorName
                                   ,@systemUsername
                                   ,@ucc);
                                        SELECT CAST(SCOPE_IDENTITY() as int)";
    
                    var strUom = fixedPriceUnitIfMeasureTypeCode != null ? fixedPriceUnitIfMeasureTypeCode.ToString() : null;
    
                    return conn.ExecuteScalar<int>(query,
                        new
                        {
                            customPriceColumnId,
                            customPriceRuleLevel,
                            itemId,
                            manufactuerCompanyId,
                            commodityId,
                            baseColumnPriceTypeId,
                            operationTypeId,
                            customPriceRuleValue,
                            isPercent,
                            customPriceRuleDescription,
                            strUom,
                            ucc,
                            actorName,
                            systemUsername
                        });
    
                }
            }
    
            public void DeleteCustomPriceRule(int customPriceRuleId)
            {
                using (IDbConnection conn = Connection)
                {
                    var query = @"DELETE FROM [TSO].[dbo].[CustomPriceRule]
                                 WHERE [CustomPriceRuleId] = @customPriceRuleId";
    
    
                    conn.Execute(query,
                        new
                        {
                            customPriceRuleId
                        });
    
                }
            }
    
            public void DeleteCustomPriceRules(IEnumerable<int> customPriceRuleIds)
            {
                var cprIdsList = customPriceRuleIds.ToList();
    
                if (!cprIdsList.Any()) return;
    
                using (IDbConnection conn = Connection)
                {
                    var query = @"DELETE FROM [TSO].[dbo].[CustomPriceRule]
                                 WHERE [CustomPriceRuleId] in ("
                                + string.Join(",", cprIdsList)
                                + ")";
    
    
                    conn.Execute(query);
    
                }
            }
    
            public List<CustomPriceRuleForExportEntity> GetCustomPriceRulesForExport(int customPriceColumnId)
            {
                using (IDbConnection conn = Connection)
                {
                    const string query = @"SELECT 
                        cpr.CustomPriceRuleLevelID
                        ,cpr.Ucc
                        ,i.Upc
                        ,c.CommodityCode
                        ,mu.ShortName as ManufacturerShortName
                        ,i.ManufacturerCatalogCode
                        ,cpr.CustomPriceRuleDescription
                        ,cpr.BaseColumnPriceTypeId
                        ,cpr.OperationTypeId
                        ,cpr.CustomPriceRuleValue
                        ,cpr.IsPercent
                        ,cpr.ItemId
                        ,cpr.ManufacturerCompanyId
                        ,cpr.CommodityId
                        FROM TSO.dbo.CustomPriceRule cpr
                        LEFT OUTER JOIN TSO.dbo.Item i ON cpr.ItemId = i.ItemId
                        LEFT OUTER JOIN TSO.dbo.ManufacturerUcc mu
                            ON ((cpr.CustomPriceRuleLevelId <> 1 AND cpr.ManufacturerCompanyId = mu.CompanyID AND cpr.UCC = mu.UCC)
                            OR (cpr.CustomPriceRuleLevelId = 1 AND LEFT(i.UPC, 6) = mu.UCC) and i.ManufacturerCompanyID = mu.CompanyID)
                        LEFT OUTER JOIN TSO.dbo.Commodity c ON cpr.CommodityId = c.CommodityId
                        WHERE cpr.CustomPriceColumnId = @customPriceColumnId";
    
                    return conn.Query<CustomPriceRuleForExportEntity>(query, new { @customPriceColumnId = customPriceColumnId }).ToList();
                }
            }
    
            #endregion
    
            public bool IsAllowedToModifyCustomPriceColumn(int userId, int customPriceColumnId)
            {
                using (IDbConnection conn = Connection)
                {
                    // Check access to CP colummn.
                    var getCpQuery = @"SELECT [CustomPriceColumnID]
                    FROM [CustomPriceColumn] cpc
                    JOIN [User] u ON u.UserId = @userId
                    WHERE cpc.[CustomPriceColumnId] = @customPriceColumnId
                    AND ((cpc.[CreatedByUserID] = @userId) /* Created by the User */
                    OR (cpc.EntityID = u.CompanyId and cpc.EntityTypeID = 0 AND CustomPriceColumnTypeID = 2)) /* OR CREATED BY SOMEONE IN THE COMPANY AND MARKED PUBLIC-EDITABLE */"; 
                    return conn.Query<CustomPriceColumnModel>(getCpQuery, new { @customPriceColumnId = customPriceColumnId, @userId = userId }).SingleOrDefault() != null;
    
                }
            }
        }
    }
    
    SELECT   s.session_id, 
            r.status, 
            r.blocking_session_id                                 'Blk by', 
            r.wait_type, 
            wait_resource, 
            r.wait_time / (1000.0)                             'Wait Sec', 
            r.cpu_time, 
            r.logical_reads, 
            r.reads, 
            r.writes, 
            r.total_elapsed_time / (1000.0)                    'Elaps Sec', 
            Substring(st.TEXT,(r.statement_start_offset / 2) + 1, 
                    ((CASE r.statement_end_offset 
                        WHEN -1 
                        THEN Datalength(st.TEXT) 
                        ELSE r.statement_end_offset 
                        END - r.statement_start_offset) / 2) + 1) AS statement_text, 
            Coalesce(Quotename(Db_name(st.dbid)) + N'.' + Quotename(Object_schema_name(st.objectid,st.dbid)) + N'.' + Quotename(Object_name(st.objectid,st.dbid)), 
                    '') AS command_text, 
            r.command, 
            s.login_name, 
            s.host_name, 
            s.program_name, 
            s.last_request_end_time, 
            s.login_time, 
            r.open_transaction_count 
            FROM     sys.dm_exec_sessions AS s 
            JOIN sys.dm_exec_requests AS r 
            ON r.session_id = s.session_id 
            CROSS APPLY sys.Dm_exec_sql_text(r.sql_handle) AS st 
            WHERE    r.session_id = 122
            ORDER BY r.cpu_time desc, r.status, 
            r.blocking_session_id, 
            s.session_id 
    
    public T WithConnection<T>(Func<IDbConnection, T> dbOperation)
        {
            try
            {
                using (var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["DatabaseName"].ConnectionString))
                {
                    var result = dbOperation(connection);
                    connection.Close();
                    return result;
                }
            }
            catch (TimeoutException ex)
            {
                throw new Exception(String.Format("{0}.WithConnection() experienced a SQL timeout", GetType().FullName), ex);
            }
            catch (SqlException ex)
            {
                throw new Exception(String.Format("{0}.WithConnection() experienced a SQL exception (not a timeout)", GetType().FullName), ex);
            }
            catch (InvalidOperationException ex)
            {
                throw new Exception(String.Format("{0}.WithConnection() experienced a InvalidOperationException", GetType().FullName), ex);
            }
        }
    
    return WithConnection(c =>
            {
                return c.Query<int>(sql,new { actId=actId}).FirstOrDefault();
            });
    
     class DapperWrapper<T>
    {        
        private static string connectionString = "your connection string";
    
        public static List<T> Get_List(string query, DynamicParameters args = null)
        {
            var watch = System.Diagnostics.Stopwatch.StartNew();
    
            List<T> result = new List<T>();
    
            try
            {
                using (var connection = new SqlConnection(connectionString))
                {
                    connection.Open();
    
                    result = connection.Query<T>(query, args).ToList();
    
                    connection.Close();
                }
    
                return result;
            }
            catch (Exception ex)
            {
                SqlException(query, ex.Message, watch.ElapsedMilliseconds);
            }
            finally
            {
                watch.Stop();
            }
    
            return null;
        }
    
        public static T Get_Single(string query, DynamicParameters args = null)
        {
            T result;
    
            var watch = System.Diagnostics.Stopwatch.StartNew();
    
            try
            {
                using (var connection = new SqlConnection(connectionString))
                {
                    connection.Open();
    
                    result = connection.Query<T>(query, args).FirstOrDefault();
    
                    connection.Close();
                }
    
                return result;
            }
            catch (Exception ex)
            {
                SqlException(query, ex.Message, watch.ElapsedMilliseconds);
            }
            finally
            {
                watch.Stop();
            }
    
            return default(T);
        }
    
        public static bool Execute(string query, DynamicParameters args = null, Log logSuccess = null)
        {
            var watch = System.Diagnostics.Stopwatch.StartNew();
    
            try
            {
                using (var connection = new SqlConnection(connectionString))
                {
                    connection.Open();
    
                    var isSuccess = connection.Execute(query, args)> 0;
    
                    if (isSuccess && logSuccess != null)
                        Logs.Add(logSuccess);
    
                    connection.Close();
    
                    return isSuccess;
                }
            }
            catch (Exception ex)
            {
                SqlException(query, ex.Message, watch.ElapsedMilliseconds);
            }
            finally
            {                
                watch.Stop();
            }
    
            return false;
        }
    
        private static void SqlException(string query, string exception, long elapsedMilliseconds)
        {
            var error = $"query : {query} → exception : {exception} → time : {elapsedMilliseconds}";
    
            Logs.Add(
                new Log()
                {
                    Title = "Error in dapper",
                    Description = error
                }
            );
        }
    }
    
    #------------Get list
    IList<Post> posts = DapperWrapper<Post>.Get_List("SELECT * FROM posts");
    
    #------------Get single
    Post post = DapperWrapper<Post>.Get_Single("SELECT * FROM posts where id=1");
    
    #------------Excute
    bool isSuccess = DapperWrapper<Post>.Execute("DELETE posts where id=1");
    
    #------------Excute with parameter
    SqlParameter[] parameters = {
                            new SqlParameter("@Id",1)
    };
    var args = new DynamicParameters(new { });    
    parameters.ToList().ForEach(p => args.Add(p.ParameterName, p.Value));
    
    bool isSuccess = DapperWrapper<Post>.Execute("DELETE posts where id=@Id", args);