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

时间:2015-07-21 06:16:37

标签: c# asp.net .net sql-server dapper

所以我已经阅读了很多链接/ SO问题,但我仍然无法得到明确的答案。

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

这是我目前关注的模式:

using (var db = new SqlConnection(_connectionString))
{
    return db.Query("dbo.SomeQuery");
}

基本上,每次根据需要打开/关闭SQL连接。

根据我的理解,上面的代码应该自动打开/关闭SQL连接(例如,我不需要明确做db.Opendb.Close)。

我看到的问题是,过了一段时间,我得到了一堆这些错误:

  

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

在此期间我有一个SQL探查器跟踪,并且我没有看到任何会阻止任何内容的长查询,因此看起来好像我的ASP.NET Web应用程序连接不足(而不是花太长时间来执行查询)。

有人可以告诉我我做错了吗?

旁注:我的应用程序是作为Azure Web App运行的,所以很遗憾,我无法实际看到Web应用程序正在打开多少个连接。 :(

7 个答案:

答案 0 :(得分:1)

这里是内部使用Dapper的数据库上下文的一个示例,我认为这是好的最佳实践。我将其整合到一个项目中,它具有不断发展的变化,来自不同地方的最佳创意以及我自己的一些经验/投入。此上下文还示例了不同类型的数据库操作:

  • 标量
  • 列表
  • 单个实体
  • 删除
  • 更新
  • 动态查询构建
  • 获取新插入的记录ID
  • 使用SqlMapper.GridReader处理多个结果集

此外,ASP.NET Core Options模式用于注入设置/连接字符串信息,与Dapper无关,但我仍然很容易看到,因为Dapper在.NET应用程序中大量使用。

我介绍了一种代码风格的概念,即将与原始数据混合在一起的类称为“实体”,并将为调用者清除的转换后的数据称为“模型”。 “ ViewModel”专用于我的堆栈中的前端。有时,上下文会向调用者返回模型,有时会返回原始实体,因为调用者需要原始实体进行深度转换,而不是上下文应负责。这个概念可能不是完美的,我在某些方面自行弥补,因为我发现“模型”一词在不同的堆栈,团队和公司中具有多种含义。我们为世界建模,数据库可以被称为模型,实体可以被视为模型...无论如何,我所说的是一门艺术和一门科学,只是试图在下面的代码中更好地解释返回类型。 :)

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;

            }
        }
    }
}

答案 1 :(得分:0)

从我的观点来看,使用语句关闭你的连接,但你告诉明确打开这样的连接:

using (var db = new SqlConnection(_connectionString))

{
       db.open();

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

答案 2 :(得分:0)

using块将处理资源管理,因此您不需要手动关闭连接,此外,手动关闭连接还会阻止连接池并降低性能。

答案 3 :(得分:0)

根据我对这种非常相似的体验的经验,超时可能是由于SQL连接超时引起的。这可能是因为,假设您的SQL Server在X核心服务器上运行,并且所有可能的最大连接数被并发调用使用,随后的调用进入等待模式。如果未指定,它将采用默认的连接超时。

您可能想在连接字符串或数据存储层中覆盖它。检查ConnectionTimeout属性。

答案 4 :(得分:0)

在我看来,您的代码很好,Dapper会打开和关闭集合本身,但是您得到的例外是因为连接池没有空闲连接可在超时时间返回。其原因可能是:

  1. 您的查询是长期运行的
  2. 对于您所承载的用户,您的连接池大小较小 有(默认为100)
  3. 1和2的组合

因此,根据您的需要调整连接池大小,并调整查询和数据库本身。或使用更大的连接超时。

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

答案 5 :(得分:0)

我遇到了您的问题。我用dapper做我的工作项目。我也遇到过同样的问题。

查找打开的连接

首先,您应该对SQL Server执行“ sp_who2”以打开sql连接

此代码返回:总连接大小,数据库名称,被阻止的人和状态

例如:

spwho2

此图像是在Azure Sql数据库中拍摄的

    "diff": [
  "1" : "2 days ago",

输入会话ID以查找查询

更改查询方法

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);
        }
    }

这解决了我的问题

答案 6 :(得分:0)

我为dapper定义了通用包装器:)

 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);