当前位置: 首页 > backend >正文

.NET 6 + Dapper + User-Defined Table Type

大家都知道,对于SQL Server IN是有限制条件的,如果IN里面的内容过多,在执行的时候会被自动截断,因而导致查询到的结果不是实际需要的结果。

select * from Payments where Id in (1,2,3,4,...)

为了解决上面的限制,可以改为利用用户自定义数据类型解决。

具体内容如下:

1. Create User-Defined Data Types

CREATE TYPE [dbo].[IdTable] AS TABLE([Id] [int] NOT NULL
)
GO

2. Create Store Procedure which use IdTable as Input paramter.

CREATE PROCEDURE [dbo].[SP_GET_PAYMENTS]                  @PaymentIds [dbo].[IdTable] READONLY                 
AS   
BEGIN  select p.Id,p.DueDate   from @PaymentIds tp     join Payments p with (nolock) on tp.Id=p.Id 
END  

3. Parameter convert to IdTable. SQLMapper Extension

  public static class Extensions{/// <summary>/// This extension converts an enumerable set to a Dapper TVP/// </summary>/// <typeparam name="T">type of enumerbale</typeparam>/// <param name="enumerable">list of values</param>/// <param name="typeName">database type name</param>/// <param name="orderedColumnNames">if more than one column in a TVP, /// columns order must mtach order of columns in TVP</param>/// <returns>a custom query parameter</returns>public static SqlMapper.ICustomQueryParameter AsTableValuedParameter<T>(this IEnumerable<T> enumerable,string typeName, IEnumerable<string> orderedColumnNames = null){var dataTable = new DataTable();if (typeof(T).IsValueType || typeof(T).FullName.Equals("System.String")){dataTable.Columns.Add(orderedColumnNames == null ?"NONAME" : orderedColumnNames.First(), typeof(T));foreach (T obj in enumerable){dataTable.Rows.Add(obj);}}else{PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);PropertyInfo[] readableProperties = properties.Where(w => w.CanRead).ToArray();if (readableProperties.Length > 1 && orderedColumnNames == null)throw new ArgumentException("Ordered list of column names must be provided when TVP contains more than one column");var columnNames = (orderedColumnNames ??readableProperties.Select(s => s.Name)).ToArray();foreach (string name in columnNames){dataTable.Columns.Add(name, readableProperties.Single(s => s.Name.Equals(name)).PropertyType);}foreach (T obj in enumerable){dataTable.Rows.Add(columnNames.Select(s => readableProperties.Single(s2 => s2.Name.Equals(s)).GetValue(obj)).ToArray());}}return dataTable.AsTableValuedParameter(typeName);}}

4. Dapper code

Dapper version: 2.1.37

using System;
using System.Configuration;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Reflection;
using Dapper;
using log4net;
using Microsoft.Data.SqlClient;
using static Dapper.SqlMapper;public List<T> QueryEntitiesNoUTC<T>(string sqlCommand, object parameters, CommandType commandType, int commandTimeout = 60){using (SqlConnection Connection = GetSqlConnection(ConfigurationManager.ConnectionStrings["Default"].ConnectionString)){try{Connection.Open();List<T> returnValues = Connection.Query<T>(sqlCommand, parameters, commandType: commandType, commandTimeout: GetCommandTimeout(commandTimeout)).ToList<T>();Connection.Close();Connection.Dispose();return returnValues;}catch (Exception e){Log.Error(e);throw;}finally{Connection.Close();Connection.Dispose();}}}

5. C# call Demo

        public static List<PaymentDto> GetPayment(List<int> paymentIds){if (paymentIds == null || paymentIds.Count == 0){return new();}var param = new { PaymentIds = paymentIds.AsTableValuedParameter("dbo.IdTable", new List<string>() { "Id" }) };var result = dapperHelper.QueryEntitiesNoUTC<PaymentDto>("SP_GET_PAYMENTS", param, CommandType.StoredProcedure, SqlConstants.GetBiggerRecordsTimeoutSeconds);return result;}

如果是多个参数:

var param = new { PaymentIds= paymentIds.AsTableValuedParameter("dbo.IdTable", new List<string>() { "Id" }), Status= status};

http://www.xdnf.cn/news/1422.html

相关文章:

  • 缓存与数据库一致性方案
  • 数据分析:用Excel做周报
  • Android开发常用外部组件及使用指南(上)
  • maple实现移位算法
  • 智驭未来:NVIDIA自动驾驶安全白皮书与实验室创新实践深度解析
  • Dart Flutter数据类型详解 int double String bool list Map
  • 亚远景-基于ASPICE标准的汽车软件过程优化路径
  • 电路中的DGND、GROUND、GROUND_REF的区别,VREF、VCC、VDD、VEE和VSS的区别?
  • Django 实现电影推荐系统:从搭建到功能完善(附源码)
  • AutoGPT超详细教程
  • SQL 时间转换的CONVERT()函数应用说明
  • Sentinel源码—9.限流算法的实现对比二
  • HSTL详解
  • 容器化-Docker-进阶
  • 高光谱相机在工业检测中的应用:LED屏检、PCB板缺陷检测
  • 软件项目实施全流程及交付物清单
  • 【教学类-102-17】蝴蝶三色图(用最大长宽作图,填入横板和竖版共16个WORD单元格模版大小,制作大小图)
  • Lodash 初学指南(适用于 Vue 3)​
  • 如何将IDP映射属性添加,到accountToken中 方便项目获取登录人信息
  • centos7部署k8s集群
  • 介绍 IntelliJ IDEA 快捷键操作
  • OpenBayes 一周速览|EasyControl 高效控制 DiT 架构,助力吉卜力风图像一键生成;TripoSG 单图秒变高保真 3D 模型
  • 移动端使用keep-alive将页面缓存和滚动缓存具体实现方法 - 详解
  • 【数据结构和算法】6. 哈希表
  • 无人船 | 图解基于PID控制的路径跟踪算法(以欠驱动无人艇Otter为例)
  • 解锁现代生活健康密码,开启养生新方式
  • 计算机网络笔记(六)——1.6计算机网络的性能
  • Tomcat 8 启动闪退解决方案:版本差异与调试技巧详解
  • React 5 种组件提取思路与实践
  • Linux系统编程---精灵进程与守护进程