友价商城SQL注入 - 卿先生 - 博客园

mikel阅读(265)

来源: 友价商城SQL注入 – 卿先生 – 博客园

友价商城SQL注入

 源码出自:https://www.0766city.com/yuanma/9990.html

 

 

下载安装好后打开是这样的:

 

 

8不说了 ,seay审计一把梭哈

 

 

从开始审计 直到这处疑似有注入的地方:

文件地址:/config/return.php

 

 

 

点进去查看代码

 

 

 

可以看到一个$aid变量被带入数据库查询语句,我们跟踪这个变量的来源,看看是否做了什么过滤操作。

 

 

而这里这里发现是函数returntype的一个形参,我们跟踪这个returntype函数,看看在哪里调用了这个函数

 

 

 

可以看到很多处,我们得一处一处去审计

 

直到发现这处

 

 

 

 

在/tem/protype2.php有个调用returntype函数的地方

跟进/tem/protype2.php

 

 

 

发现用$type1name这个变量接收returntype函数的返回值,而我们这个$aid那个形参也就是程序这里传入的$_GET[type1lid],我们关注这个参数,

 

 

 

 

可以看到没有经过任何过滤,造成SQL注入

 

 

 

复现:

 

注入漏洞文件地址:tem/protype2.php

注入参数:type1id

 

 

 

 

 

.net core使用CSRedisCore访问Redis主从+哨兵_.net core csredis_sundna的博客-CSDN博客

mikel阅读(266)

来源: .net core使用CSRedisCore访问Redis主从+哨兵_.net core csredis_sundna的博客-CSDN博客

本文主要目的是对Redis主从+哨兵的高可用方案进行实验,文中使用的技术不进行深入说明,想深入了解的可自行百度。

用到的软件和版本:

CSRedisCore版本:3.0.6.2 (https://github.com/2881099/csredis)
Redis版本:3.2.100 (windows)

1. 下载Redis安装包
本示例使用Windows10搭建Redis环境,Windows下的Redis下载方式如下

打开网址 https://github.com/microsoftarchive/redis/releases,下载3.2.100的压缩包

 

2. 搭建Redis主从集群
将压缩包解压然后复制,总共3份,我们搭建1主2从模式,Redis6379(主),Redis6479(从),Redis6579(从)

 

主Redis配置,进入Redis6379目录中,配置 redis.windows.conf

#配置IP绑定
bind 0.0.0.0
#配置端口
port 6379
#是否保护模式
protected-mode no
为了方便运行,目录下加个run.bat文件

redis-server redis.windows.conf
从Redis配置,分别进入Redis6479和Redis6579目录,配置redis.windows.conf,并添加run.bat文件

#配置IP绑定
bind 0.0.0.0
#配置端口,分别配置6479和6579
port 6479
#是否保护模式
protected-mode no
#配置主redisd的IP和端口
slaveof 192.168.1.5 6379
现在Redis配置好了,运行3个Redis目录中的run.bat启动服务,运行后可以看到主从都成功连接。

 

3.搭建哨兵
实际使用中一般会使用多个哨兵进行监控,本文作了简化,只使用1个哨兵,多个哨兵都是相同的配置,仅区分端口。

将Redis目录复制一份命名为RedisSentinel,添加sentinel.conf文件,内容如下:

port 27000 #哨兵运行端口
protected-mode no #非保护模式运行
#监控的主Redis的IP和端口,1表示1个哨兵
sentinel monitor redis-master 192.168.1.5 6379 1
#主机掉线以后5s进行认证,如果无法连接则重新由哨兵从slave中选出新的master
sentinel down-after-milliseconds redis-master 5000
sentinel failover-timeout redis-master 60000
CMD中通过命令运行哨兵

redis-server sentinel.conf –sentinel
可以看到哨兵已经发现1主2从并开始监听了

 

也可通过命令查看哨兵状态

redis-cli -p 27000 info sentinel

4. .NET Core中使用Redis集群
我们使用CSRedisCore来访问Redis,CSRedisCore是国内大牛开发的一个.net core redis 组件,源码可读性很强非常干净,几乎无任何依赖。性能相比ServiceStack.Redis和StackExchange.Redis会快10%左右,支持Redis的高级特性:订阅/发布,Pipeline,MGet/MSet,集群,分区。

创建一个.net core 控制台程序,然后添加nuget包

nuget Install-Package CSRedisCore
Program.cs代码

using System;
using System.Threading;

namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
//连接哨兵
var csredis = new CSRedis.CSRedisClient(“redis-master”, new[] {“127.0.0.1:27000” });

//初始化 RedisHelper
RedisHelper.Initialization(csredis);

while (true)
{
try
{
Test();
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.ReadLine();
}
Console.ReadKey();
}

static void Test()
{
RedisHelper.Set(“name”, “祝雷”);//设置值。默认永不过期
Console.WriteLine(RedisHelper.Get<String>(“name”));

RedisHelper.Set(“time”, DateTime.Now, 1);
Console.WriteLine(RedisHelper.Get<DateTime>(“time”));
Console.WriteLine(RedisHelper.Get<DateTime>(“time”));

// 列表
RedisHelper.RPush(“list”, “第一个元素”);
RedisHelper.RPush(“list”, “第二个元素”);
RedisHelper.LInsertBefore(“list”, “第二个元素”, “我是新插入的第二个元素!”);
Console.WriteLine($”list的长度为{RedisHelper.LLen(“list”)}”);
Console.WriteLine($”list的第二个元素为{RedisHelper.LIndex(“list”, 1)}”);
}
}
}
模拟故障进行测试,启动程序后,杀死主Redis进程,.net core程序再次访问Redis会出现一次异常检查,然后能正常切换到新的master上。

————————————————
版权声明:本文为CSDN博主「sundna」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sundna/article/details/94133931

自学如何训练/调教一个私人ChatGPT - 知乎

mikel阅读(560)

来源: 自学如何训练/调教一个私人ChatGPT – 知乎

每周更新一丢丢~欢迎大佬来指正

训练步骤

训练一个个人化的GPT模型大概可以分为以下几个步骤:

  1. 数据收集:收集与个人领域相关的数据,这些数据应该足够多且多样化。数据集应该是和你的应用场景相关的,例如针对特定的领域或者任务。
  2. 数据清理和预处理:将数据进行清理,去除噪声和冗余,统一数据格式,进行标记和编码等预处理。
  3. 模型选择:选择一个基础的GPT模型,可以选择已经公开的预训练模型,也可以选择自己训练的模型(如果你有大量的计算资源和时间,同时学习过TensorFlow或PyTorch等深度学习框架)。
  4. 微调模型:将收集到的个人数据和已经训练好的GPT模型进行微调,让模型更好地适应个人领域。
  5. 模型测试和优化:通过测试来评估模型的性能,并进行优化,提高模型的准确性和效率。
  6. 部署:将训练好的模型部署到生产环境中,供用户使用。

可以用的预训练模型

目前已经公开的预训练模型有很多,其中比较常用的包括:

  • GPT-2
  • GPT-3
  • BERT
  • RoBERTa
  • T5
  • XLNet

这些模型都具有一定的训练难度,但可以根据具体需求和场景选择适合的模型。其中

  • GPT-2是比较经典的模型之一,训练难度相对较小,但是效果也不错。
  • GPT-3则是当前最为先进的预训练模型之一,拥有极高的自然语言处理能力,但是训练难度较大,需要较高的计算资源和数据量。
  • BERT和RoBERTa则主要应用于文本分类、问答等任务,效果也比较不错。
  • T5则可以用于各种NLP任务的生成式模型,可以生成文本、代码等。
  • XLNet是一种比较新的预训练模型,在许多NLP任务上都表现出色,尤其是在涉及长序列、多文档或多轮对话的任务中。例如,XLNet在阅读理解、文本分类、序列标注和生成任务等方面表现出色。此外,XLNet还可以在多语言和跨语言任务中应用,因为它可以处理多种语言之间的语言交叉性。

电脑小白可不可以训练?

没问题!

但需要先学习一些基础的编程和机器学习知识,以便更好地理解和使用GPT-2预训练模型。

训练GPT-2预训练模型必须的编程知识主要包括以下几个方面:
1. Python编程语言:GPT-2是使用Python编写的,因此需要掌握Python编程语言基础知识,如变量、函数、数据类型、流程控制等。
2. 深度学习框架:训练GPT-2需要使用深度学习框架,如TensorFlow、PyTorch等。需要掌握框架的基本概念、模型构建、模型训练和模型调优等。
3. 自然语言处理:GPT-2是基于自然语言处理技术的深度学习模型,需要掌握自然语言处理基础知识,如文本处理、分词、词向量、语言模型等。
4. 计算机硬件和操作系统:GPT-2训练需要大量计算资源,需要了解计算机硬件配置和操作系统的基础知识,如CPU、GPU、内存、磁盘、Linux操作系统等。
5. 数据处理和存储:训练GPT-2需要处理大量的数据,需要掌握数据处理和存储的基本知识,如数据清洗、数据抽取、数据存储等。
6. 数学基础:深度学习是一种数学模型,需要掌握一些数学基础知识,如线性代数、微积分、概率论等。

关于如何使用GPT-2预训练模型,以下是一些基本的步骤:

  1. 下载预训练模型:可以从Hugging Face等网站下载预训练模型。
  2. 安装必要的库:需要安装Python、PyTorch等库来加载模型。
  3. 加载模型:使用Python代码加载预训练模型。
  4. 输入数据:将要生成文本的前缀输入到模型中。
  5. 生成文本:使用模型生成新的文本。

编程小白如何起步

如果你是零基础,建议你先学习一些基础编程知识,例如 Python 编程语言、命令行操作、基本的数据结构和算法等等。可以通过一些在线课程、教材或者学习网站来学习这些知识。

对于训练 GPT-2 预训练模型,你需要学习深度学习的基本概念和技术,包括神经网络、反向传播算法、优化器、损失函数等等。同时,你还需要了解自然语言处理领域的相关知识,例如文本预处理、语言模型等等。

一些经验丰富的数据科学家或者研究人员会建议你先从预训练模型的 fine-tuning 开始,这个过程不需要你自己训练一个完整的预训练模型,而是使用已经训练好的模型来完成一个特定的任务,例如文本分类或者生成文本等等。在这个过程中,你可以了解到如何调整模型参数、如何构建输入数据和输出数据等等技术细节。这也是一个更加容易入门的方法。

笔记本电脑可以训练吗?

可以的,尽管性能不会那么好,但够用了。

个人笔记本电脑可以尝试:

  1. 使用小型的语言模型来微调
  2. 使用预训练的模型,如GPT-2或BERT,并将其微调到特定任务中。在微调模型之前,还需要准备好相应的数据集,并决定如何设置模型的超参数。为了获得更好的微调效果,建议使用一些技巧,如数据增强和模型融合。

预训练模型的内存大小会因不同的模型规模而有所不同。以GPT-2模型为例,它的规模包括117M、345M、774M、1558M、3450M等不同大小的模型。其中,117M的模型需要约0.5GB的内存,而3450M的模型需要约17GB的内存。

电脑系统有影响吗?

使用哪种操作系统并不会直接影响使用GPT-2等预训练模型的能力。预训练模型可以在Windows和macOS上运行,但是在选择操作系统时,可能需要考虑以下因素:

  1. 设备性能:无论选择哪种操作系统,电脑都需要具备足够的处理能力和存储空间来运行预训练模型。
  2. 软件支持:在使用预训练模型时,需要安装Python、TensorFlow或PyTorch等软件。这些软件都可以在Windows和macOS上运行,但是可能需要查看它们在不同操作系统上的安装和配置方式。
  3. 开发环境:如果打算进行模型微调和训练,可能需要选择一个操作系统来搭建开发环境。例如,如果打算使用Docker容器运行模型,需要选择支持Docker的操作系统。

总之,选择操作系统主要取决于个人的需求和偏好,不会直接影响使用预训练模型的能力。

无需GPU无需网络“本地部署chatGPT”(更新中文模型)_Pangaroo的博客-CSDN博客

mikel阅读(464)

来源: 无需GPU无需网络“本地部署chatGPT”(更新中文模型)_Pangaroo的博客-CSDN博客

想当初图像生成从DELL到stable diffusion再到苹果的移动部署过了两三年吧
聊天bot才发展几个月就可以边缘部署了,如果苹果更新silicon,npu和运存翻倍,争取apple watch也能本地内置,最快ios18 mac、ipad、iPhone能内置吧
又是一个平民百姓都高兴的开源项目,chatGPT这种级别的模型甚至能部署到树莓派上运行,然后在操作的过程中也遇到一些问题,这篇就是记录步数的这个过程。
最近github那边更新了,我踩坑遇到的问题已经不痛用了,但我暂时又没时间研究这个,干脆好人做到底,把未更新的代码贴在下面。
已经为最新版的github更新了(2023.4.7),可以放心食用,不用下载下面的老代码链接了。

链接: https://pan.baidu.com/s/1J9FBxSDhmBcqAnHx3rGhEQ 提取码: q5xv
–来自百度网盘超级会员v6的分享
然后配合下面的模型百度云链接,大家应该就可以自己搭建语言模型了。

大佬的网址:https://github.com/ggerganov/llama.cpp

下载及生成
打开命令行输入下面的指令

git clone https://github.com/ggerganov/llama.cpp
cd llama.cpp
make

#对于Windows和CMake,使用下面的方法构建:
cd <path_to_llama_folder>
mkdir build
cd build
cmake ..
cmake –build . –config Release
1
2
3
4
5
6
7
8
9
10

模型下载
我觉得模型下载是最麻烦的,还好有别人给了

git clone https://huggingface.co/nyanko7/LLaMA-7B
1
好吧我直接给百度云
链接: https://pan.baidu.com/s/1ZC2SCG9X8jZ-GysavQl29Q 提取码: 4ret
–来自百度网盘超级会员v6的分享

 

然后安装python依赖,然后转换模型到FP16格式。然后第一个小bug会出现。

python3 -m pip install torch numpy sentencepiece

# convert the 7B model to ggml FP16 format
python3 convert-pth-to-ggml.py models/7B/ 1
1
2
3
4

他会报找不到文件。

打开convert-pth-to-ggml.py文件,修改”/tokenizer.model”的路径,再运行python3 convert-pth-to-gaml.py ./models/7B 1,我顺便名字也改了。

文件找到了,然后出现第二个bug。。。。。

我一开始找不出问题,后来对比原网址和7B文件夹里的文件,才发现文件大小根本都不一样,我说几十个G的东西怎么git这么。
打开网站下图这个网址,点红色框的那两个下载。替换掉7B文件夹里的那两个文件。

 

将模型再转换成4位格式

# quantize the model to 4-bits
./quantize ./models/7B/ggml-model-f16.bin ./models/7B/ggml-model-q4_0.bin 2
1
2

推理
# run the inference
./main -m ./models/7B/ggml-model-q4_0.bin -n 128
1
2

想和chatGPT一样对话的话用下面这个指令,-n 控制回复生成的最大长度, –color是区分ai和人类的颜色,-i 作为参数在交互模式下运行, -r 是一种反向提示,-f 是一整段提示, –repeat_penalty 控制生成回复中对重复文本的惩罚力度,–temp 温度系数,值越低回复的随机性越小,反之越大。
更新了之后速度快了很多。

./main -m ./models/7B/ggml-model-q4_0.bin -n 256 –repeat_penalty 1.0 –color -i -r “User:” -f prompts/chat-with-bob.txt
1
让我们打开prompts/chat-with-bob.txt来看一下。

我们可以看到这相当于给了ai模型一个场景话题,然后你和ai之间就可以接着这个话题聊天。

我英文名叫zale,然后我把这个机器人叫作kangaroo,这样的身份和他聊天,你可以按自己的喜欢自己修改下面的代码。

./main -m ./models/7B/ggml-model-q4_0.bin -n 256 –repeat_penalty 1.0 –color -i -r “Zale:” \
1
写一个txt文件

“Transcript of a dialog, where the Zale interacts with an Assistant named Kangaroo. Kangaroo is helpful, kind, honest, good at writing, and never fails to answer the Zale’s requests immediately and with precision.

Zale: Hello, Kangaroo.
Kangaroo: Hello. How may I help you today?
Zale: Please tell me the largest city in Europe.
Kangaroo: Sure. The largest city in Europe is Moscow, the capital of Russia.
Zale:”

1
2
3
4
5
6
7
8

有点呆呆的,不过也算边缘部署的巨大进步了!
一个蛮有意思的发现,明明看得懂中文却跟我说不懂中文。。。。。

分享一段有意思的对话

中文部署
哈工大的github
https://github.com/ymcui/Chinese-LLaMA-Alpaca

git clone https://github.com/ymcui/Chinese-LLaMA-Alpaca.git
1
下载中文模型,但这不是llama.cpp要输入的模型,官方的说明是llama的中文补丁模型,需要和原版的llama/alpaca模型合并才能使用。

安装依赖

pip install git+https://github.com/huggingface/transformers
pip install sentencepiece
pip install peft
1
2
3
为了方便起见,我把llama原文件也放到了这里

还有一些注意事项

查看sha256,每个平台查看方式略微不同,可以上网搜一下如何查看sha256

整理一下llama原文件的路径

我是将transformers下载到conda里了,路径有点长。你就是找到你的convert_llama_weights_to_hf.py文件的路径就好。

python /Users/kangaroo/miniconda3/envs/pytorch/lib/python3.10/site-packages/transformers/models/llama/convert_llama_weights_to_hf.py \
–input_dir ./llama_7b \
–model_size 7B \
–output_dir ./llama_hf
1
2
3
4

合并模型

python scripts/merge_llama_with_chinese_lora.py \
–base_model ./llama_hf \
–lora_model ./chinese_llama_lora_7b \
–output_dir ./cn_llama
1
2
3
4

再把这个文件夹复制到llama.cpp/models 中

回到llama.cpp里重新量化

python convert-pth-to-ggml.py models/cn_llama/ 1

./quantize ./models/cn_llama/ggml-model-f16.bin ./models/cn_llama/ggml-model-q4_0.bin 2
1
2
3
有点话痨,我直接掐掉了,之后再看看

./main -m ./models/cn_llama/ggml-model-q4_0.bin -n 48 –repeat_penalty 1.0 –color -i -r “Zale:” -f prompts/chat-with-zale.txt
1

./main -m models/cn_llama/ggml-model-q4_0.bin –color -f ./prompts/alpaca.txt -ins -c 2048 –temp 0.2 -n 256 –repeat_penalty 1.3
1

————————————————
版权声明:本文为CSDN博主「Pangaroo」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_45569617/article/details/129553293

JavaScript 对象与 JSON 对象的相互转换_js json转换_latency_cheng的博客-CSDN博客

mikel阅读(265)

来源: JavaScript 对象与 JSON 对象的相互转换_js json转换_latency_cheng的博客-CSDN博客

一、全局JSON对象
ES5定义了全局对象JSON,对解析JSON的行为制定了规范。
JSON对象有两个方法:stringify() 和 parse()。

二、JavaScript 对象序列化为 JSON对象
JSON.stringify( js对象 [, 过滤器] [, 选项])
二三参数可选,js对象中的函数和原型成员将被忽略,值为undefined的属性也被跳过。
默认情况下,返回的JSON不包含任何空格字符和缩进。
var book = {
title: “Professional JavaScript”,
authors: [“Nicholas C. Zakas”],
edition: 3,
year: 2011
};

var jsonText = JSON.stringify(book);

过滤器为数组:JSON.stingify() 的结果只包含数组中列出的属性。
var book = {
title: “Professional JavaScript”,
authors: [“Nicholas C. Zakas”],
edition: 3,
year: 2011
};

var jsonText = JSON.stringify(book, [“title”, “edition”]);
jsonText的值为 {“title”: “Professional JavaScript”, “edition”: 3}

过滤器为函数:函数接收两个参数,键名和值(key, value)。函数体中根据键名处理对应的值。
var book = {
title: “Professional JavaScript”,
authors: [“Nicholas C. Zakas”],
edition: 3,
year: 2011
};

var jsonText = JSON.stringify(book, function(key, value){
switch(key){
case “authors”:
return value.join(“,”)
case “year”:
return 5000;
case “edition”:
return undefined;
default:
return value;
}
});
序列化后的 jsonText 值为:{“title”: “Professional JavaScript”, “authors”: “Nicholas C. Zakas”, “year”: 5000}

第三个参数用于控制结果的缩进:
参数为数值 —– 表示缩进的空格数。
var book = {
title: “Professional JavaScript”,
authors: [“Nicholas C. Zakas”],
edition: 3,
year: 2011
};

var jsonText = JSON.stringify(book, null, 4);
jsonText 中的字符串:
{
“title”: “Professional JavaScript”,
“authors”: [
“Nicholas C. Zakas”
],
“edition”: 3,
“year”: 2011
}

参数为字符串 —– 表示使用该字符串进行缩进。
var book = {
title: “Professional JavaScript”,
authors: [“Nicholas C. Zakas”],
edition: 3,
year: 2011
};

var jsonText = JSON.stringify(book, null, ” – -“);
jsonText 中的字符串:
{
–“title”: “Professional JavaScript”,
–“authors”: [
—-“Nicholas C. Zakas”
–],
–“edition”: 3,
–“year”: 2011
}

(还可以为对象定义 toJSON() 方法,实现对其进行自定义序列化的需求。)

三、JSON对象解析为 JavaScript 对象
JSON.parse(json对象 [, 还原函数])
还原参数接收两个参数,键和值。如果返回undefined,则表示从结果中删除相应的键;如果返回其他值,则将该值插入到结果中。
var book = {
title: “Professional JavaScript”,
authors: [“Nicholas C. Zakas”],
edition: 3,
year: 2011,
releaseDate: new Date(2011, 11, 1)
};

var jsonText = JSON.stringify(book);
var bookCopy = JSON.parse(jsonText, function(key, value){
if (key == “releaseDate”){
return new Date(value);
} else {
return value;
}
});
————————————————
版权声明:本文为CSDN博主「latency_cheng」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/latency_cheng/article/details/73468205

SQLServer数据库中常用的3种分页查询方法

mikel阅读(315)

SQLServer中,常用的分页查询有以下几种:

  1. 使用OFFSET-FETCH语句:该语句从指定偏移量开始返回指定行数的结果集。

例如:

SELECT *

FROM table_name

ORDER BY column_name

OFFSET 10 ROWS

FETCH NEXT 5 ROWS ONLY;

这将从第11行开始返回5行结果集。

注意:这种方法对SQLServer版本有要求,需要SQLServer2012以后的版本才支持

2、使用ROW_NUMBER()函数:该函数为结果集中的每一行分配一个行号,然后可以根据行号进行分页。

例如:

WITH CTE AS (

  SELECT *, ROW_NUMBER() OVER (ORDER BY column_name) AS RowNum

  FROM table_name

)

SELECT *

FROM CTE

WHERE RowNum BETWEEN 11 AND 15; 这将返回第11行到第15行之间的结果集。

3、使用TOP语句和子查询:该方法可以通过子查询返回指定行数的结果集,然后使用TOP语句从子查询中选择前N行。

例如:

SELECT TOP 5 *

FROM (

  SELECT *, ROW_NUMBER() OVER (ORDER BY column_name) AS RowNum

  FROM table_name

) AS subquery

WHERE RowNum > 10;

这将返回第11行到第15行之间的结果集。

需要注意的是,在处理大量数据时,分页查询可能会影响性能。因此,可以考虑使用其他技术来优化查询。例如,可以使用索引或缓存数据以提高性能。

另外,还可以使用存储过程或视图来实现分页查询。存储过程是一组预定义的SQL语句,可以在需要时执行。视图是一种虚拟表,可以从一个或多个表中检索数据。以下是使用存储过程和视图实现分页查询的示例:

使用存储过程:该方法可以将分页查询逻辑封装在存储过程中,然后可以轻松地调用该存储过程以进行分页查询。例如:

CREATE PROCEDURE GetPageResults

  @PageNumber INT,

  @PageSize INT

AS

BEGIN

  SELECT *

  FROM table_name

  ORDER BY column_name

  OFFSET (@PageNumber – 1) * @PageSize ROWS

  FETCH NEXT @PageSize ROWS  ONLY;

END; 

 然后可以使用以下语句调用存储过程:

EXEC GetPageResults @PageNumber = 2, @PageSize = 5;

这将返回第6行到第10行之间的结果集。

使用视图:该方法可以创建一个虚拟表来存储所有数据,然后可以使用分页查询从该视图中检索数据。例如:

CREATE VIEW vw_table_name AS

SELECT *, ROW_NUMBER() OVER (ORDER BY column_name) AS RowNum

FROM table_name;

然后可以使用以下语句进行分页查询:

SELECT *

FROM vw_table_name

WHERE RowNum BETWEEN 11 AND 15;

这将返回第11行到第15行之间的结果集。

需要注意的是,在使用存储过程或视图时,需要考虑安全性和性能。

存储过程可以提高查询性能并减少SQL注入攻击的风险,但需要更多的开发和管理工作。视图可以提供简单的查询和安全性,但可能会影响性能。决定使用哪种方法取决于具体情况,需要根据实际需要进行权衡。

最后,需要注意的是,以上分页查询示例可能需要根据具体情况进行修改。例如,需要根据实际列名和表名来替换相应的名称。同时需要根据具体需求调整分页查询的参数,如每页显示的行数、需要显示的页码等。

此外,还需要注意以下几个问题:

数据库引擎版本:不同版本的SQL Server可能支持不同的分页查询语法和特性。因此,在编写分页查询语句时,需要考虑数据库引擎的版本。

查询复杂度:如果查询涉及多个表、多个条件或计算密集型操作,可能需要采用优化技术来提高查询性能。例如,可以使用索引、查询优化器或缓存数据等技术。

数据库结构:数据库结构对查询性能和分页查询的实现方式也有很大影响。例如,如果表中没有主键或排序字段,则可能需要采用其他技术来实现分页查询。

数据库访问权限:在实际应用中,需要根据不同的用户角色和权限来限制对数据库的访问和查询。因此,在编写分页查询语句时,需要考虑用户权限和安全性问题。

并发访问:在高并发环境下,多个用户同时访问数据库可能会导致性能问题。因此,在编写分页查询语句时,需要考虑并发访问的情况,并采用适当的技术来避免或减少性能问题。

综上所述,SQL Server提供了多种分页查询语法和技术,开发人员可以根据具体情况选择适当的方法来实现分页查询。同时,需要考虑数据库

引擎版本、查询复杂度、数据库结构、数据库访问权限和并发访问等因素,以确保查询性能和安全性。

ChatGPT 本地部署及搭建_孟郎郎的博客-CSDN博客

mikel阅读(700)

来源: (1条消息) ChatGPT 本地部署及搭建_孟郎郎的博客-CSDN博客

这篇简要说下清华开源项目 ChatGLM 本地部署的详细教程。清华开源项目 ChatGLM-6B 已发布开源版本,这一项目可以直接部署在本地计算机上做测试,无需联网即可体验与 AI 聊天的乐趣。

项目地址:GitHub – THUDM/ChatGLM-6B: ChatGLM-6B:开源双语对话语言模型 | An Open Bilingual Dialogue Language Model

官网介绍:

ChatGLM-6B 是一个开源的、支持中英双语的对话语言模型,基于 General Language Model (GLM) 架构,具有 62 亿参数。结合模型量化技术,用户可以在消费级的显卡上进行本地部署(INT4 量化级别下最低只需 6GB 显存)。 ChatGLM-6B 使用了和 ChatGPT 相似的技术,针对中文问答和对话进行了优化。经过约 1T 标识符的中英双语训练,辅以监督微调、反馈自助、人类反馈强化学习等技术的加持,62 亿参数的 ChatGLM-6B 已经能生成相当符合人类偏好的回答,更多信息请参考我们的博客。

为了方便下游开发者针对自己的应用场景定制模型,我们同时实现了基于 P-Tuning v2 的高效参数微调方法 (使用指南) ,INT4 量化级别下最低只需 7GB 显存即可启动微调。

不过,由于 ChatGLM-6B 的规模较小,目前已知其具有相当多的局限性,如事实性/数学逻辑错误,可能生成有害/有偏见内容,较弱的上下文能力,自我认知混乱,以及对英文指示生成与中文指示完全矛盾的内容。请大家在使用前了解这些问题,以免产生误解。更大的基于 1300 亿参数 GLM-130B 的 ChatGLM 正在内测开发中。

第一步,本地安装 Python
这一步暂略,可以自行下载安装 Python 环境。

Python 下载地址:Download Python | Python.org

注意:安装 >9 以上版本,建议安装 10。

第二步,下载项目程序包
地址见上面的项目地址,直接下载下来并解压。我这里解压到 E:\chatGPT\ 下。

 

第三步,下载模型包 chatglm
下载地址:https://huggingface.co/THUDM/chatglm-6b/tree/main

官网介绍:

ChatGLM-6B 是一个开源的、支持中英双语问答的对话语言模型,基于 General Language Model (GLM) 架构,具有 62 亿参数。结合模型量化技术,用户可以在消费级的显卡上进行本地部署(INT4 量化级别下最低只需 6GB 显存)。ChatGLM-6B 使用了和 ChatGLM 相同的技术,针对中文问答和对话进行了优化。经过约 1T 标识符的中英双语训练,辅以监督微调、反馈自助、人类反馈强化学习等技术的加持,62 亿参数的 ChatGLM-6B 已经能生成相当符合人类偏好的回答。

注意:下载后放到第二步程序包下,自行创建目录 chatglm-6b,如下:

 

第四步,下载依赖包
Window + R 快捷键打开运行窗口,输入 cmd 打开控制台命令行,进入到程序目录下。

 

分别执行如下两条命令:

pip install -r requirements.txt

pip install gradio

注意:如果执行有报错,请查阅文章末尾的错误处理。

 

等待依赖包下载成功,结果如下:

 

第五步,运行网页版 demo
执行如下命令,运行网页版本的 demo,如下:

python web_demo.py

程序会运行一个 Web Server,并输出地址。在浏览器中打开输出的地址即可使用。最新版 Demo 实现了打字机效果,速度体验大大提升。注意,由于国内 Gradio 的网络访问较为缓慢,启用 demo.queue().launch(share=True, inbrowser=True) 时所有网络会经过 Gradio 服务器转发,导致打字机体验大幅下降,现在默认启动方式已经改为 share=False,如有需要公网访问的需求,可以重新修改为 share=True 启动。

执行结果如下:

 

注意:如果执行提示信息和上图对不上,请查阅文章末尾的错误处理。

第七步,测试网页版程序
浏览器打开地址 并访问,输入问题,可以看到 ChatGLM 会给予回复。

 

Very Good!查看电脑性能,感觉 CPU 和内存都要爆掉了 ^ ^

 

 

第八步,运行命令行 Demo
执行如下命令,运行命令行版本的 demo,如下:

python cli_demo.py

程序会在命令行中进行交互式的对话,在命令行中输入指示并回车即可生成回复,输入 clear 可以清空对话历史,输入 stop 终止程序。

 

错误一:下载依赖包超时
E:\chatGPT\ChatGLM-6B-main>pip install -r requirements.txt
Collecting protobuf<3.20.1,>=3.19.5
Downloading protobuf-3.20.0-cp310-cp310-win_amd64.whl (903 kB)
—————————————- 903.8/903.8 kB 4.0 kB/s eta 0:00:00
Collecting transformers==4.27.1
Downloading transformers-4.27.1-py3-none-any.whl (6.7 MB)
———– —————————- 2.0/6.7 MB 5.4 kB/s eta 0:14:29
ERROR: Exception:
Traceback (most recent call last):
File “D:\Python\Python310\lib\site-packages\pip\_vendor\urllib3\response.py”, line 438, in _error_catcher
yield
File “D:\Python\Python310\lib\site-packages\pip\_vendor\urllib3\response.py”, line 561, in read
data = self._fp_read(amt) if not fp_closed else b””
File “D:\Python\Python310\lib\site-packages\pip\_vendor\urllib3\response.py”, line 527, in _fp_read
return self._fp.read(amt) if amt is not None else self._fp.read()
File “D:\Python\Python310\lib\site-packages\pip\_vendor\cachecontrol\filewrapper.py”, line 90, in read
data = self.__fp.read(amt)
File “D:\Python\Python310\lib\http\client.py”, line 465, in read
s = self.fp.read(amt)
File “D:\Python\Python310\lib\socket.py”, line 705, in readinto
return self._sock.recv_into(b)
File “D:\Python\Python310\lib\ssl.py”, line 1274, in recv_into
return self.read(nbytes, buffer)
File “D:\Python\Python310\lib\ssl.py”, line 1130, in read
return self._sslobj.read(len, buffer)
TimeoutError: The read operation timed out

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “D:\Python\Python310\lib\site-packages\pip\_internal\cli\base_command.py”, line 160, in exc_logging_wrapper
status = run_func(*args)
File “D:\Python\Python310\lib\site-packages\pip\_internal\cli\req_command.py”, line 247, in wrapper
return func(self, options, args)
File “D:\Python\Python310\lib\site-packages\pip\_internal\commands\install.py”, line 419, in run
requirement_set = resolver.resolve(
File “D:\Python\Python310\lib\site-packages\pip\_internal\resolution\resolvelib\resolver.py”, line 92, in resolve
result = self._result = resolver.resolve(
File “D:\Python\Python310\lib\site-packages\pip\_vendor\resolvelib\resolvers.py”, line 481, in resolve
state = resolution.resolve(requirements, max_rounds=max_rounds)
File “D:\Python\Python310\lib\site-packages\pip\_vendor\resolvelib\resolvers.py”, line 348, in resolve
self._add_to_criteria(self.state.criteria, r, parent=None)
File “D:\Python\Python310\lib\site-packages\pip\_vendor\resolvelib\resolvers.py”, line 172, in _add_to_criteria
if not criterion.candidates:
File “D:\Python\Python310\lib\site-packages\pip\_vendor\resolvelib\structs.py”, line 151, in __bool__
return bool(self._sequence)
File “D:\Python\Python310\lib\site-packages\pip\_internal\resolution\resolvelib\found_candidates.py”, line 155, in __bool__
return any(self)
File “D:\Python\Python310\lib\site-packages\pip\_internal\resolution\resolvelib\found_candidates.py”, line 143, in <genexpr>
return (c for c in iterator if id(c) not in self._incompatible_ids)
File “D:\Python\Python310\lib\site-packages\pip\_internal\resolution\resolvelib\found_candidates.py”, line 47, in _iter_built
candidate = func()
File “D:\Python\Python310\lib\site-packages\pip\_internal\resolution\resolvelib\factory.py”, line 206, in _make_candidate_from_link
self._link_candidate_cache[link] = LinkCandidate(
File “D:\Python\Python310\lib\site-packages\pip\_internal\resolution\resolvelib\candidates.py”, line 297, in __init__
super().__init__(
File “D:\Python\Python310\lib\site-packages\pip\_internal\resolution\resolvelib\candidates.py”, line 162, in __init__
self.dist = self._prepare()
File “D:\Python\Python310\lib\site-packages\pip\_internal\resolution\resolvelib\candidates.py”, line 231, in _prepare
dist = self._prepare_distribution()
File “D:\Python\Python310\lib\site-packages\pip\_internal\resolution\resolvelib\candidates.py”, line 308, in _prepare_distribution
return preparer.prepare_linked_requirement(self._ireq, parallel_builds=True)
File “D:\Python\Python310\lib\site-packages\pip\_internal\operations\prepare.py”, line 491, in prepare_linked_requirement
return self._prepare_linked_requirement(req, parallel_builds)
File “D:\Python\Python310\lib\site-packages\pip\_internal\operations\prepare.py”, line 536, in _prepare_linked_requirement
local_file = unpack_url(
File “D:\Python\Python310\lib\site-packages\pip\_internal\operations\prepare.py”, line 166, in unpack_url
file = get_http_url(
File “D:\Python\Python310\lib\site-packages\pip\_internal\operations\prepare.py”, line 107, in get_http_url
from_path, content_type = download(link, temp_dir.path)
File “D:\Python\Python310\lib\site-packages\pip\_internal\network\download.py”, line 147, in __call__
for chunk in chunks:
File “D:\Python\Python310\lib\site-packages\pip\_internal\cli\progress_bars.py”, line 53, in _rich_progress_bar
for chunk in iterable:
File “D:\Python\Python310\lib\site-packages\pip\_internal\network\utils.py”, line 63, in response_chunks
for chunk in response.raw.stream(
File “D:\Python\Python310\lib\site-packages\pip\_vendor\urllib3\response.py”, line 622, in stream
data = self.read(amt=amt, decode_content=decode_content)
File “D:\Python\Python310\lib\site-packages\pip\_vendor\urllib3\response.py”, line 560, in read
with self._error_catcher():
File “D:\Python\Python310\lib\contextlib.py”, line 153, in __exit__
self.gen.throw(typ, value, traceback)
File “D:\Python\Python310\lib\site-packages\pip\_vendor\urllib3\response.py”, line 443, in _error_catcher
raise ReadTimeoutError(self._pool, None, “Read timed out.”)
pip._vendor.urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host=’files.pythonhosted.org’, port=443): Read timed out.

E:\chatGPT\ChatGLM-6B-main>

可以看到错误信息提示超时,应该是网络问题,可以尝试在命令中加上超时时间设置的参数,命令修改后如下:

pip –default-timeout=1688 install -r requirements.txt

问题二:又一次实时下载模型包

当运行程序时,如果提示信息中看到又一次下载模型包,而没有使用第三步提前准备的模型包时,需要把模型包复制到程序运行时的缓存目录中,缓存路径可能如下:

C:\Users\用户目录\.cache\huggingface\hub\models–THUDM–chatglm-6b\snapshots\fb23542cfe773f89b72a6ff58c3a57895b664a23

模型包拷贝到该目录后再次运行程序即可。

Good Luck!
————————————————
版权声明:本文为CSDN博主「孟郎郎」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/tzhuwb/article/details/129910616

 

轻量高效ORM之Dapper篇 - 知乎

mikel阅读(683)

来源: 轻量高效ORM之Dapper篇 – 知乎

介绍

dapper是一个简单的对象关系映射框架(ORM—-Object Relation Mapping),它几乎与原始的ADO.NET 数据操作读取一样快(反正我ado.net已经忘完了╥__╥,以前用的最多是linq to SQL和ef,不需要写SQL语句,使用linq操作数据源),它负责数据库与编程语言之间的映射。

与EF的优劣

EF——-重量级ORM的代表

优点:

  • 面向对象式操作数据库。
  • 完全摆脱SQL 语句,不用关心SQL如何写,可移植性强。
  • 支持code first,开发人员可以完成且无需关心数据库,代码先行,极大节省开发成本。
  • 结合LINQ,开发效率高。
  • 跨数据库,易配置。
  • 与VS结合较好。

缺点:

  • 比较复杂,学习曲线复杂(官方文档丰富且杂)。
  • 不适合做统计查询(因为统计查询需要执行查询效率高)。
  • 对于多表查询或一些复杂的查询实现较为困难和复杂。
  • 自动生成的SQL语句复杂,效率低。
  • EF的Context上下文不是线程安全的(知识有限,不懂)。
  • 包和插件较为冗余(对于中小型项目来说),性能一般。

Dapper——–轻量级ORM的代表

优点:

  • 开源,轻巧(轻量级),编译后文件简单且小巧。
  • 支持主流数据库,MSSQL,MySQL,Oracle。
  • 执行效率高。
  • 学习较为方便

缺点:

  • 半自动ORM,需要开发人员自己写实体类┭┮﹏┭┮(可以借助实体类生成工具生成)。
  • 开发时间成本高,LINQ支持较弱。
  • 维护成本高,不支持Code first,开发人员除了要维护数据库中的表,还需要维护代码表中的映射对象。

Dapper安装

Nuget包安装管理器搜索,安装最新版本即可。

Dapper方法

Dapper使用以下几个方法扩展了我们的IDbConnection接口

  • Execute
  • Query
  • QueryFirst
  • QueryFirstOrDefault
  • QuerySingle
  • QuerySingleOrDefault
  • QueryMultiple

Execute

可执行存储过程、增、删、改等操作。

此处以插入为例

MySqlConnection实现了DbConnection接口,当数据库发生改变时,可进行更改。

插入(单、多),更新(单、多),删除(单,多)均使用此方法

Query

Dapper Contrib插件

它是额外的插件,在dapper的基础上进一步封装了些许操作,使开发更为方便。

安装包之后,即可使用。

数据注释

ExplicitKey和Computed这两个属性后面遇到再阐述

基本方法

今日总结,皆为初步学习,有很多方法没有涉及到,具体后期在实践中总结。

Dapper.Common基于Dapper的开源LINQ超轻量扩展 - 腾讯云开发者社区-腾讯云

mikel阅读(309)

来源: Dapper.Common基于Dapper的开源LINQ超轻量扩展 – 腾讯云开发者社区-腾讯云

Dapper.Common是基于Dapper的LINQ实现,支持.net core,遵循Linq语法规则、链式调用、配置简单、上手快,支持MySQL,SQLServer(目前只实现了这两个数据库,实现其他数据库也很轻松),支持单表,多表,自定义函数等功能。源码及其简单,直白,解析Lambda只有300行左右代码。严格区分C#函数和数据库函数,你可以在表达式中调用C#函数(不推荐,推荐将计算结果保存到变量,在写入lambda表达式),性能损失在表达式编译:常量>变量>函数。损失多少可以通过ExpressionUtil.BuildExpression()来测试,几万次耗时百毫秒级别。

开源地址:https://github.com/1448376744/Dapper.Common

Nuget:Install-Package Dapper.Common -Version 1.5.0

测试

映射

public class User
  {
       /// <summary>
       /// 如果表名与字段名一致,可以不用Column进行注解,主键采用类型的第一个属性【不推荐】
       /// name:用于映射字段名和数据库字段不一致【完全可以用T4一键生成我GitHub有现成的】
       /// key:
       ///     目前实现了Primary的定义,设置为Primary的字段update实体时,默认采用该字段为更新条件
       /// isIdentity:
       ///     设置未true时在Insert时不会向该字段设置任何值
       /// isColumn:
       ///     标识该字段是否在数据库存在,用于扩展User而不在sql中生成该字段
       /// </summary>
       [Column(name: "id", key: ColumnKey.Primary, isIdentity: true, isColumn: true)]
       public int? Id { get; set; }
       [Column(name:"nick_name")]
       public string NickName { get; set; }
       [Column(name: "create_time")]
       public DateTime? CreateTime { get; set; }
  }

配置

//在App启动时执行一次即可
SessionFactory.AddDataSource(new DataSource()
{
    Name = "mysql",
    Source = () => new SqlConnection("connectionString"),
    SourceType = DataSourceType.SQLSERVER,
    UseProxy = true//使用Session的静态代理实现,记录日志,执行耗时,线上环境建议关闭代理
});

//获取数据库上下文
using (var session = SessionFactory.GetSession("msql"))
{
    //linq to sql
}

使用

1.Insert

var entity = new User()
{
    CreateTime=DateTime.Now,
    NickName="dapper",
};
//绝大部分接口可以设置condition已决定是否执行,支持批量更新
session.From<User>().Insert(entity,condition:1>2);
//查看日志,如果出现异常,应该在catch里,查看session.Loggers
var loggers = session.Loggers;

2.Update

var entity = new User()
{
  Id=2,
  NickName="李四"
};
//更新所有字段(where id=2),支持批量,显然除NickName之外将被更新成null
session.From<User>().Update(entity);

//更新部分字段
session.From<User>()
   .Set(a => a.NickName, "李四", condition: true)//condition为true时更新该字段
   .Set(a => a.Balance, a => a.Balance + 100)//余额在原来基础增加100
   .Where(a => a.Id.In(1,2,3))//将id为1,2,3的记录进行更新
   .Update();

3.Delete

//删除id>5||nick_name like '%da%'
 session.From<User>()
    .Where(a=>a.Id>5||a.NickName.Like("da"))
    .Delete();

4.Single

//查询全部字段
  var user1 = session.From<User>()
      .Where(a=>a.Id==2)
      .Single();

  //查询部分字段
  var user2 = session.From<User>()
     .Where(a => a.Id == 2)
     .Single(s=>new
     {
         s.Id,
         s.NickName
     });

5.Select

//查询:where id in(1,2,3)
 var list = session.From<User>()
        .Where(a => a.Id.In("1,2,3".Split(',')))
        .Select();

6.Where

//构建动态查询,condition: true执行,通过condition选择分支,多个where之间用 and 连接
 var list = session.From<User>()
        .Where(a => a.Id.In(1, 2, 3), condition: true)
        .Where(a => a.NickName.Like("da"), condition: false)
        .Where(a => a.Id > 2 || (a.NickName.Like("da") && a.Balance > 50))
        .Where("select * from user_bill where user_bill.user_id=user.id")//同样可以当作字符串拼接工具
        .Select();

7.Function

/// <summary>
 /// 自定义函数
 /// </summary>
 public static class MySqlFun
 {
     //这里使用泛型并不是必须的,只用函数名在数据库存在即可,泛型为了指定返回数据类型
     [Function]//Dapper.Common严格区分C#函数和数据库函数,一定要用该特性标识数据库函数
     public static T COUNT<T>(T column)
     {
         return default(T);
     }
     [Function]
     public static T MAX<T>(T column)
     {
         return default(T);
     }
     [Function]
     public static T DISTINCT<T>(T column)
     {
         return default(T);
     }
   [Function]
   public static T DATE<T>(T column)
     {
     return default(T);
   }
  }

8.GroupBy

var list = session.From<Order>()
     .GroupBy(a => a.UserId)//多个条件可以new一个匿名对象,也可以并联多个group
     .Having(a => MySqlFun.COUNT(MySqlFun.DISTINCT(a.UserId)) > 10)//count(distinct(user_id))>10
     .Select(s => new
     {
         s.UserId,
         OrderCount = MySqlFun.COUNT(1L),//这里应该返回long int,
         MaxFee = MySqlFun.MAX(s.TotalFee)
     });

9.Join

var list = session.From<Order, User>()
     .Join((a, b) => a.UserId == b.Id, JoinType.Inner)
     .GroupBy((a, b) => a.UserId)
     .Having((a, b) => MySqlFun.COUNT(MySqlFun.DISTINCT(a.UserId)) > 10)//count(distinct(user_id))>10
     .Select((a, b) => new
     {
         a.UserId,
         b.NickName,
         OrderCount = MySqlFun.COUNT(1L),//这里应该返回long int,
         MaxFee = MySqlFun.MAX(a.TotalFee)
     });

10.SubQuery

var list = session.From<Order>()
    .GroupBy(a  => a.UserId)
    .Having(a => MySqlFun.COUNT(MySqlFun.DISTINCT(a.UserId)) > 10)
    .Select(a => new
    {
        a.UserId,
        UserName=Convert.ToString("select nick_name from user where user.id=order.user_id"),//如果这个子查询返回的是int:Convert.ToInt32(sql)
        OrderCount = MySqlFun.COUNT(1L),//这里应该返回long int【这就是为什么定义成泛型函数】,
        MaxFee = MySqlFun.MAX(a.TotalFee)
    });

11.Page

//分页应该写在Where,Having,Group之后(如果有)
var list = session.From<User>()
        .Where(a=>a.NickName != null)
        .Page(1,10,out long total)
        .Select();

12.Take

var list = session.From<User>()
        .Take(5)
        .Select();

13.Skip

//从数据库索引为1的位置(跳过1之前的记录),获取10
var list = session.From<User>()
    .Skip(1,10)
    .Select();

14.Sum

var list= session.From<User>()
     .Sum(s=>s.Balance*s.Id);

15.Exists

//内部采用exist子查询判断满足where条件的记录是否存在
var flag = seesion.From<User>()
    .Where(a=>a.Id > 10)
    .Exists();

16.OrderBy

var list1 = session.From<User>()
    .Order(a=>a.Id)
    .Select();

var list2 = session.From<User>()
    .GroupBy(a => MysqlFun.DATE(a.CreateTime))
    .OrderByDescending(a => MysqlFun.DATE(a.CreateTime))
    .Select(s=>new 
    {
         Date=MysqlFun.DATE(s.CreateTime),
         Count = MysqlFun.Count(1L)
    });

17.Filter

var user =new User ()
{
  Id = 12
  Balance = 50,
  NickName = "张三",
  CreateTime = Datetime.Now
};
//Filter会在Insert,Update,Select,过滤掉不想要的字段
//这将不会更新余额及创建时间
var row = session.From<User>()
    .Filter(f=>new 
    {
          f.CreateTime,
          f.Balance,
    })
    .Update(user);

18.Transaction

//获取数据库上下文
  ISession session = null;
  try
  {
    session=SessionFactory.GetSession();
      //开启事务
      session.Open(true);
      //sql
      //提交事务
      session.Commit();
  }
  catch (Exception)
  {
      session?.Rollback();
      throw;
  }
  finally
  {
      session?.Close();
  }

原文地址:https://cnblogs.com/chaeyeon/p/11028480.html

c# Dapper,添加,修改,删除,查询,事务,存储过程,含数据库(从入门到高级)_橙-极纪元的博客-CSDN博客

mikel阅读(437)

来源: c# Dapper,添加,修改,删除,查询,事务,存储过程,含数据库(从入门到高级)_橙-极纪元的博客-CSDN博客

目录

前言

介绍

重点提示

安装

使用NuGet安装

准备工作

数据库SQL (含存储过程)

模型类

Type.cs

Product.cs

数据库访问层

引入关键库

创建数据库连接

添加 3个方法

1.新增一条数据,不带事务

2.新增一条数据,且,返回自增ID;不带事务

3.新增多条数据,不带事务

修改 2个方法

1.修改一条数据,不带事务

2.修改多条数据,不带事务

删除 2个方法

1.删除一条数据,不带事务

2.删除多条数据,不带事务

查询/Join查询/函数查询/查询In操作/多语句查询/验证类型名是否存在 7个方法

1.查询一条数据

2.普通查询-列表

3.Join查询-列表

4.函数查询 和,平均值,最大值,最小值

5.查询In操作

6.多语句查询

7.验证类型名是否存在

事务 3个方法

1.事务第一种用法;添加一条分类的同时新增一条产品数据

2.事务第二种用法;添加一条分类的同时新增一条产品数据

3.新增(添加)多条数据,带事务

执行存储过程 3个方法

1.查询产品表,根据类型ID 查询出所有产品,且返回产品数量

SQL

2.插入新产品的存储过程,产品名存在就不插入

sql

3.获取产品表和产品类型表中的所有数据

sql

 

前言
介绍
C# Dapper高级编程;
添加方法3个,

修改方法2个,

删除方法2个,

查询方法7个(含Join),

事务方法3个,

存储过程方法3个

重点提示
一、ORM框架执行效率排序EF 7 8 Dapper执行效率 1 2

二、传参

传参有三种方式
第一种:model模型传参 如:User user=new User(); user.name=”小明”
第二种:匿名类型传参 如:var user = new {name=”小明”};
第三种:DynamicParameters 传参 如下:
DynamicParameters paras = new DynamicParameters();
paras.Add(“@name”, “小明”);//输入参数

三、

只有在BeginTransaction(事务)时要求连接是打开的conn.Open()。
而在不使用事务的时候,简单的增删改查可以不用这一句dbConnection.Open()(即conn.Open());
因为Dapper的大部分方法中有dbConnection.Open(),所以不需要每次都打开连接,程序会自己处理。

安装
使用NuGet安装
项目》引用》右键》管理NuGet程序包》左侧出现界面》浏览》输入“Dapper”》选中》左侧有个“安装”》点击安装

在解决方案管理器中点击项目,查看引用,如果有Dapper,说明安装成功。

 

准备工作
数据库sql (含存储过程)
USE [master]
GO
/****** Object: Database [DBTase] Script Date: 2020/11/20 10:22:57 ******/
CREATE DATABASE [DBTase]
CONTAINMENT = NONE
ON PRIMARY
( NAME = N’DBTase’, FILENAME = N’C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLServer\MSSQL\DATA\DBTase.mdf’ , SIZE = 5120KB , MAXSIZE = UNLIMITED, FILEGROWTH = 1024KB )
LOG ON
( NAME = N’DBTase_log’, FILENAME = N’C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLServer\MSSQL\DATA\DBTase_log.ldf’ , SIZE = 1024KB , MAXSIZE = 2048GB , FILEGROWTH = 10%)
GO
ALTER DATABASE [DBTase] SET COMPATIBILITY_LEVEL = 110
GO
IF (1 = FULLTEXTSERVICEPROPERTY(‘IsFullTextInstalled’))
begin
EXEC [DBTase].[dbo].[sp_fulltext_database] @action = ‘enable’
end
GO
ALTER DATABASE [DBTase] SET ANSI_NULL_DEFAULT OFF
GO
ALTER DATABASE [DBTase] SET ANSI_NULLS OFF
GO
ALTER DATABASE [DBTase] SET ANSI_PADDING OFF
GO
ALTER DATABASE [DBTase] SET ANSI_WARNINGS OFF
GO
ALTER DATABASE [DBTase] SET ARITHABORT OFF
GO
ALTER DATABASE [DBTase] SET AUTO_CLOSE OFF
GO
ALTER DATABASE [DBTase] SET AUTO_CREATE_STATISTICS ON
GO
ALTER DATABASE [DBTase] SET AUTO_SHRINK OFF
GO
ALTER DATABASE [DBTase] SET AUTO_UPDATE_STATISTICS ON
GO
ALTER DATABASE [DBTase] SET CURSOR_CLOSE_ON_COMMIT OFF
GO
ALTER DATABASE [DBTase] SET CURSOR_DEFAULT GLOBAL
GO
ALTER DATABASE [DBTase] SET CONCAT_NULL_YIELDS_NULL OFF
GO
ALTER DATABASE [DBTase] SET NUMERIC_ROUNDABORT OFF
GO
ALTER DATABASE [DBTase] SET QUOTED_IDENTIFIER OFF
GO
ALTER DATABASE [DBTase] SET RECURSIVE_TRIGGERS OFF
GO
ALTER DATABASE [DBTase] SET DISABLE_BROKER
GO
ALTER DATABASE [DBTase] SET AUTO_UPDATE_STATISTICS_ASYNC OFF
GO
ALTER DATABASE [DBTase] SET DATE_CORRELATION_OPTIMIZATION OFF
GO
ALTER DATABASE [DBTase] SET TRUSTWORTHY OFF
GO
ALTER DATABASE [DBTase] SET ALLOW_SNAPSHOT_ISOLATION OFF
GO
ALTER DATABASE [DBTase] SET PARAMETERIZATION SIMPLE
GO
ALTER DATABASE [DBTase] SET READ_COMMITTED_SNAPSHOT OFF
GO
ALTER DATABASE [DBTase] SET HONOR_BROKER_PRIORITY OFF
GO
ALTER DATABASE [DBTase] SET RECOVERY FULL
GO
ALTER DATABASE [DBTase] SET MULTI_USER
GO
ALTER DATABASE [DBTase] SET PAGE_VERIFY CHECKSUM
GO
ALTER DATABASE [DBTase] SET DB_CHAINING OFF
GO
ALTER DATABASE [DBTase] SET FILESTREAM( NON_TRANSACTED_ACCESS = OFF )
GO
ALTER DATABASE [DBTase] SET TARGET_RECOVERY_TIME = 0 SECONDS
GO
EXEC sys.sp_db_vardecimal_storage_format N’DBTase’, N’ON’
GO
USE [DBTase]
GO
/****** Object: StoredProcedure [dbo].[cp_petowner] Script Date: 2020/11/20 10:22:57 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[cp_petowner]
AS
select * from product

GO
/****** Object: StoredProcedure [dbo].[cp_petowner_VarCharValue] Script Date: 2020/11/20 10:22:57 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
–2.创建一个带参数的存储过程
CREATE PROCEDURE [dbo].[cp_petowner_VarCharValue]
@ownername varchar(50)
AS
DECLARE @ownername2 varchar(50)
set @ownername2=’小米手机’
select *,@ownername as ownername from product where name=@ownername2

GO
/****** Object: StoredProcedure [dbo].[PROC_Product] Script Date: 2020/11/20 10:22:57 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
–【存储过程】查询产品表,根据类型ID 查询出所有产品,且返回产品数量
create proc [dbo].[PROC_Product]
@typeID int,
@count int out
as
begin

select @count=COUNT(ID) from Product where TypeID=@typeID;

select * from Product where TypeID=@typeID;
end

GO
/****** Object: StoredProcedure [dbo].[PROC_Product_insert] Script Date: 2020/11/20 10:22:57 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
–【存储过程】插入新产品的存储过程,产品名存在就不插入
create proc [dbo].[PROC_Product_insert]
@name nvarchar(50),
@typeID int ,
@count int out
as
begin
declare @c int;
select @c=COUNT(ID) from Product where Name=@name;
if(@c!=0)
set @count =0;
else
begin
insert into Product(name, typeID) values(@name,@typeID);
set @count=1;
end
end

GO
/****** Object: StoredProcedure [dbo].[PROC_TypeAndProduct] Script Date: 2020/11/20 10:22:57 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
–【存储过程】获取产品表和产品类型表中的所有数据
create procedure [dbo].[PROC_TypeAndProduct]
as
begin
select TypeID,TypeName from [Type];
select ID,TypeID,Name from Product;
end
GO
/****** Object: Table [dbo].[Product] Script Date: 2020/11/20 10:22:57 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Product](
[ID] [int] IDENTITY(1,1) NOT NULL,
[TypeID] [int] NULL,
[Name] [nvarchar](50) NULL,
CONSTRAINT [PK_Product] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
/****** Object: Table [dbo].[Type] Script Date: 2020/11/20 10:22:57 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Type](
[TypeID] [int] IDENTITY(1,1) NOT NULL,
[TypeName] [nvarchar](50) NULL,
CONSTRAINT [PK_Type] PRIMARY KEY CLUSTERED
(
[TypeID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO
SET IDENTITY_INSERT [dbo].[Product] ON

INSERT [dbo].[Product] ([ID], [TypeID], [Name]) VALUES (1, 1, N’苹果手机’)
INSERT [dbo].[Product] ([ID], [TypeID], [Name]) VALUES (3, 1, N’三星手机’)
INSERT [dbo].[Product] ([ID], [TypeID], [Name]) VALUES (4, 1, N’华为手机’)
INSERT [dbo].[Product] ([ID], [TypeID], [Name]) VALUES (5, 1, N’小米手机’)
INSERT [dbo].[Product] ([ID], [TypeID], [Name]) VALUES (7, 2, N’苹果电脑’)
INSERT [dbo].[Product] ([ID], [TypeID], [Name]) VALUES (8, 2, N’戴尔电脑’)
INSERT [dbo].[Product] ([ID], [TypeID], [Name]) VALUES (9, 3, N’小米手环’)
INSERT [dbo].[Product] ([ID], [TypeID], [Name]) VALUES (10, 3, N’华为手环’)
SET IDENTITY_INSERT [dbo].[Product] OFF
SET IDENTITY_INSERT [dbo].[Type] ON

INSERT [dbo].[Type] ([TypeID], [TypeName]) VALUES (1, N’手机’)
INSERT [dbo].[Type] ([TypeID], [TypeName]) VALUES (2, N’电脑’)
INSERT [dbo].[Type] ([TypeID], [TypeName]) VALUES (3, N’手表’)
SET IDENTITY_INSERT [dbo].[Type] OFF
ALTER TABLE [dbo].[Product] WITH CHECK ADD CONSTRAINT [FK_product_Type] FOREIGN KEY([TypeID])
REFERENCES [dbo].[Type] ([TypeID])
GO
ALTER TABLE [dbo].[Product] CHECK CONSTRAINT [FK_product_Type]
GO
USE [master]
GO
ALTER DATABASE [DBTase] SET READ_WRITE
GO
模型类
Type.cs
/// <summary>
/// 产品类型
/// </summary>
public class Type
{

/// <summary>
/// TypeID
/// </summary>
private int _typeid;
public int TypeID
{
get { return _typeid; }
set { _typeid = value; }
}
/// <summary>
/// TypeName
/// </summary>
private string _typename;
public string TypeName
{
get { return _typename; }
set { _typename = value; }
}

}
Product.cs
/// <summary>
/// 产品
/// </summary>
public class Product
{

/// <summary>
/// ID
/// </summary>
private int _id;
public int ID
{
get { return _id; }
set { _id = value; }
}
/// <summary>
/// TypeID
/// </summary>
private int _typeid;
public int TypeID
{
get { return _typeid; }
set { _typeid = value; }
}
/// <summary>
/// Name
/// </summary>
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}

public Type ProductType { get; set; }//做联表查询

}
数据库访问层
引入关键库
using System;
using System.Collections.Generic;
using System.Linq;
using Dapper;
using System.Data;
using System.Data.SqlClient;
创建数据库连接
private static string connStr = “server=.;uid=sa;pwd=sa;database=DBTase”;

添加 3个方法

1.新增一条数据,不带事务
/// <summary>
/// 新增一条数据,不带事务
/// </summary>
public static void Add()
{
string sql = @”insert into Type(TypeName) values(@TypeName)”;

Type productType = new Type()
{
TypeName = “测试类型2020-11-19”
};

using (SqlConnection conn = new SqlConnection(connStr))
{
int result = conn.Execute(sql, productType);
if (result > 0)
{
Console.WriteLine(“新增一条数据成功!”);
}
}
}
2.新增一条数据,且,返回自增ID;不带事务
/// <summary>
/// 新增一条数据,且,返回自增ID;不带事务
/// </summary>
public static void AddGetID()
{
/*
在高并发的环境中 可能得到的@@identity会不是你想要的结果
你在新增,别人也可能也在新增 。你获取的时候就是 获取到最后插入的那条记录的ID.
所以 我们要修改一下
SELECT @@identity
修改为
SELECT SCOPE_IDENTITY();
*/
string sql = @”insert into Type(TypeName) values(@TypeName);SELECT SCOPE_IDENTITY();”;

Type productType = new Type()
{
TypeName = “新增一条数据,且,返回自增ID;不带事务”
};

using (SqlConnection conn = new SqlConnection(connStr))
{
//获取新加的ID
int id = Convert.ToInt32(conn.ExecuteScalar(sql, productType));
if (id > 0)
{
Console.WriteLine(“新增一条数据,且,返回自增ID;不带事务”);
Console.WriteLine($”新增ID为:{id}”);
}
}
}
3.新增多条数据,不带事务
/// <summary>
/// 新增多条数据,不带事务
/// </summary>
public static void AddList()
{
string sql = @”insert into Type(TypeName) values(@TypeName)”;

List<Type> productTypeList = new List<Type>
{
new Type(){ TypeName = “1测试类型2020-11-19”},
new Type(){ TypeName = “2测试类型2020-11-19”},
new Type(){ TypeName = “3测试类型2020-11-19”},
new Type(){ TypeName = “4测试类型2020-11-19”},
new Type(){ TypeName = “5测试类型2020-11-19”},
new Type(){ TypeName = “6测试类型2020-11-19”}
};

using (SqlConnection conn = new SqlConnection(connStr))
{
int result = conn.Execute(sql, productTypeList);
if (result > 0)
{
Console.WriteLine(“新增多条数据,不带事务–添加成功!”);
}
}
}

 

修改 2个方法

1.修改一条数据,不带事务
/// <summary>
/// 修改一条数据,不带事务
/// </summary>
public static void Update()
{
string sql = @”update Type set TypeName=@TypeName where TypeID=@TypeID”;
Type productType = new Type()
{
TypeID = 5,
TypeName = “Update测试类型2020-11-19”
};
using (SqlConnection conn = new SqlConnection(connStr))
{
int result = conn.Execute(sql, productType);
if (result > 0)
{
Console.WriteLine(“修改一条数据成功!”);
}
}
}
2.修改多条数据,不带事务
/// <summary>
/// 修改多条数据,不带事务
/// </summary>
public static void UpdateList()
{
string sql = @”update Type set TypeName=@TypeName where TypeID=@TypeID”;
List<Type> productTypeList = new List<Type>
{
new Type(){ TypeID=6, TypeName = “1Update测试类型2020-11-19”},
new Type(){ TypeID=7, TypeName = “2Update测试类型2020-11-19”},
new Type(){ TypeID=8, TypeName = “3Update测试类型2020-11-19”},
new Type(){ TypeID=9, TypeName = “4Update测试类型2020-11-19”},
new Type(){ TypeID=10,TypeName = “5Update测试类型2020-11-19”},
new Type(){ TypeID=11,TypeName = “6Update测试类型2020-11-19”}
};
using (SqlConnection conn = new SqlConnection(connStr))
{
int result = conn.Execute(sql, productTypeList);
if (result > 0)
{
Console.WriteLine(“修改多条数据成功!”);
}
}
}

 

删除 2个方法
1.删除一条数据,不带事务
/// <summary>
/// 删除一条数据,不带事务
/// </summary>
public static void Delete()
{
string sql = @”delete Type where TypeID=@TypeID”;
Type productType = new Type();
productType.TypeID = 11;

using (SqlConnection conn = new SqlConnection(connStr))
{
//添加、删除、修改 Execute 存储过程
//update
int result = conn.Execute(sql, productType);
if (result > 0)
{
Console.WriteLine(“删除一条数据成功!”);
}
}
}

2.删除多条数据,不带事务
/// <summary>
/// 删除多条数据,不带事务
/// </summary>
public static void DeleteList()
{
string sql = @”delete Type where TypeID=@TypeID”;

List<Type> productTypeList = new List<Type>
{
new Type(){ TypeID=9},
new Type(){ TypeID=10}
};

using (SqlConnection conn = new SqlConnection(connStr))
{
//添加、删除、修改 Execute 存储过程
//update
int result = conn.Execute(sql, productTypeList);
if (result > 0)
{
Console.WriteLine(“删除多条数据成功!”);
}
}
}

 

查询/Join查询/函数查询/查询In操作/多语句查询/验证类型名是否存在 7个方法
1.查询一条数据
/// <summary>
/// 查询一条数据
/// </summary>
public static void GetModel()
{
Console.WriteLine(“******查询一条数据******”);

string sql = @”select * from Type where TypeID=@TypeID”;
Type productType = new Type();
productType.TypeID = 6;

using (SqlConnection conn = new SqlConnection(connStr))
{
Type _type = conn.Query<Type>(sql, productType).Single();
Console.WriteLine($”[ID:{_type.TypeID}]Name:{_type.TypeName}”);
}
}
2.普通查询-列表
/// <summary>
/// 普通查询-列表
/// ProductSelect产品查询
/// </summary>
public static void ProductSelect()
{
Console.WriteLine(“******普通查询-列表******”);
string sql = “select * from product”;

using (SqlConnection conn = new SqlConnection(connStr))
{
List<Product> productsList = conn.Query<Product>(sql).ToList();

Console.WriteLine(“//ProductSelect查询//”);
foreach (var item in productsList)
{
Console.WriteLine($”ID:{item.ID}\nName:{item.Name}”);
}
}

}
3.Join查询-列表
/// <summary>
/// Join查询-列表
/// ProductJoinTypeSelect产品带产品类型名称查询
/// </summary>
public static void ProductJoinTypeSelect()
{
Console.WriteLine(“******Join查询-列表******”);

string sql = @”select * from product p
left join type t
on (p.TypeID=t.TypeID)”;

using (SqlConnection conn = new SqlConnection(connStr))
{
var productsList = conn.Query<Product, Type, Product>
(sql, (product, type) =>
{
product.ProductType = type;//关联表
return product;
}, splitOn: “typeid”//建立关系的字段
).ToList();

Console.WriteLine(“//ProductJoinTypeSelect查询//”);
foreach (var item in productsList)
{
Console.WriteLine($”ID:{item.ID}\nName:{item.Name}\nTypeName:{item.ProductType.TypeName}”);
}
}

}

4.函数查询 和,平均值,最大值,最小值
/// <summary>
/// 函数查询 和,平均值,最大值,最小值
/// </summary>
public static void GetFunction()
{
Console.WriteLine(“******函数查询,和,平均值,最大值,最小值******”);

string sql = @”select * from Type”;//ORM框架执行效率排序EF 7 8 Dapper执行效率 1 2
using (SqlConnection conn = new SqlConnection(connStr))
{
List<Type> productTypeList = conn.Query<Type>(sql).ToList();
int count = productTypeList.Count();//获取记录条数
Console.WriteLine($”记录条数:{count}”);
var sum = productTypeList.Sum(p => p.TypeID);
var avg = productTypeList.Average(p => p.TypeID);
var max = productTypeList.Max(p => p.TypeID);
var min = productTypeList.Min(p => p.TypeID);
Console.WriteLine($”和 Sum:{sum}”);
Console.WriteLine($”平均值 Average:{avg}”);
Console.WriteLine($”最大值 Max:{max}”);
Console.WriteLine($”最小值 Min:{min}”);

foreach (Type t in productTypeList)
{
Console.WriteLine($”{t.TypeID}-{t.TypeName}”);
}
}
}
5.查询In操作
/// <summary>
/// 查询In操作
/// </summary>
public static void GetIn()
{
Console.WriteLine(“******查询In操作******”);

string sql = “select * from product where ID in @ids”;

int[] ids = {1,2,3,4,5};

using (SqlConnection conn = new SqlConnection(connStr))
{
List<Product> productsList = conn.Query<Product>(sql,new { ids= ids }).ToList();

foreach (var item in productsList)
{
Console.WriteLine($”ID:{item.ID}\nName:{item.Name}”);
}
}
}
6.多语句查询
/// <summary>
/// 多语句查询
/// </summary>
public static void GetMultiple()
{
Console.WriteLine(“******多语句查询******”);

string sql = “SELECT TypeID, TypeName FROM [Type];SELECT ID, TypeID, Name FROM Product”;

using (SqlConnection conn = new SqlConnection(connStr))
{
Dapper.SqlMapper.GridReader multiReader = conn.QueryMultiple(sql);

//注意:由于首先查出是Type,其次是Product,那么你在执行下面代码的时候顺序必须和sql语句顺序一致
IEnumerable<Type> typeList = multiReader.Read<Type>();
IEnumerable<Product> productList = multiReader.Read<Product>();

Console.WriteLine(“//多语句查询-类型信息”);
foreach (var item in typeList)
{
Console.WriteLine($”ID:{item.TypeID}\nName:{item.TypeName}”);
}

Console.WriteLine(“//多语句查询-产品信息”);
foreach (var item in productList)
{
Console.WriteLine($”ID:{item.ID}\nName:{item.Name}”);
}
}
}
7.验证类型名是否存在
/// <summary>
/// 验证类型名是否存在
/// </summary>
/// <param name=”name”>类型名</param>
/// <returns></returns>
public static bool Check(string name)
{
string sql = “select count(TypeName) from Type where TypeName=@TypeName”;
using (SqlConnection conn = new SqlConnection(connStr))
{
var number = conn.QueryFirst<int>(sql, new { TypeName = name });

if (number > 0)
{
return true;
}
return false;
}
}
事务 3个方法
1.事务第一种用法;添加一条分类的同时新增一条产品数据
/// <summary>
/// 事务第一种用法;添加一条分类的同时新增一条产品数据
/// </summary>
public static void ExecuteTranscationOne()
{

/*
在高并发的环境中 可能得到的@@identity会不是你想要的结果
你在新增,别人也可能也在新增 。你获取的时候就是 获取到最后插入的那条记录的ID.
所以 我们要修改一下
SELECT @@identity
修改为
SELECT SCOPE_IDENTITY();
*/
string TypeSql = @”insert into Type(TypeName) values(@TypeName);
SELECT SCOPE_IDENTITY();”;

string ProduxtSql = @”insert into Product(TypeID,Name)
values(@TypeID,@Name)”;

Type type = new Type()
{
TypeName = “新的分类1”
};
Product product = new Product()
{
TypeID = 0,
Name = “新的产品1”
};
using (SqlConnection conn = new SqlConnection(connStr))//打开数据库方式交给框架执行
{
SqlTransaction trans = null;
try
{
conn.Open();//手动打开数据库链接//在dapper中使用事务,需要手动打开连接
//程序事务,建立在某个连接对象上
//开始事务
trans = conn.BeginTransaction();//连接对象开启事务
int typeID = Convert.ToInt32(conn.ExecuteScalar(TypeSql, type, trans));
product.TypeID = typeID;
int result2 = conn.Execute(ProduxtSql, product, trans);
//提交事务(持久化数据)
trans.Commit();
if (result2 > 0)
Console.WriteLine(“事务1:添加一条数据成功”);
else
Console.WriteLine(“事务1:添加一条数据【失败】”);
}
catch (Exception ex)
{
//事务回滚
trans.Rollback();
Console.WriteLine(ex.Message);
}
}
}
2.事务第二种用法;添加一条分类的同时新增一条产品数据
/// <summary>
/// 事务第二种用法;添加一条分类的同时新增一条产品数据
/// </summary>
public static void ExecuteTranscationTwo()
{

/*
在高并发的环境中 可能得到的@@identity会不是你想要的结果
你在新增,别人也可能也在新增 。你获取的时候就是 获取到最后插入的那条记录的ID.
所以 我们要修改一下
SELECT @@identity
修改为
SELECT SCOPE_IDENTITY();
*/
string TypeSql = @”insert into Type(TypeName) values(@TypeName);
SELECT SCOPE_IDENTITY();”;

string ProduxtSql = @”insert into Product(TypeID,Name)
values(@TypeID,@Name)”;

Type type = new Type()
{
TypeName = “新的分类:事务2”
};
Product product = new Product()
{
TypeID = 0,
Name = “新的产品:事务2”
};
using (SqlConnection conn = new SqlConnection(connStr))//打开数据库方式交给框架执行
{
conn.Open();//在dapper中使用事务,需要手动打开连接

// 连接对象开启事务
//开始事务
using (SqlTransaction trans = conn.BeginTransaction())
{
try
{
//获取新加类型ID
int typeID = Convert.ToInt32(conn.ExecuteScalar(TypeSql, type, trans));
//把新的类型ID 给产品
product.TypeID = typeID;
int result2 = conn.Execute(ProduxtSql, product, trans);
//提交事务(持久化数据)
trans.Commit();

if (result2 > 0)
Console.WriteLine(“事务2:添加一条数据成功”);
else
Console.WriteLine(“事务2:添加一条数据【失败】”);
}
catch (Exception ex)
{
//事务回滚
trans.Rollback();
Console.WriteLine(ex.Message);
}
}
}
}
3.新增(添加)多条数据,带事务
/// <summary>
/// 新增多条数据,带事务
/// </summary>
public static void ExecAddList()
{
string sql = @”insert into Type(TypeID,TypeName) values(@TypeID,@TypeName)”;

List<Type> productTypeList = new List<Type>
{
new Type(){ TypeID=1, TypeName = “Exec1测试类型2020-11-20”},
new Type(){ TypeName = “Exec2测试类型2020-11-20”},
new Type(){ TypeName = “Exec3测试类型2020-11-20”},
new Type(){ TypeName = “Exec4测试类型2020-11-20”},
new Type(){ TypeName = “Exec5测试类型2020-11-20”},
new Type(){ TypeName = “Exec6测试类型2020-11-20″}
};

using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();//在dapper中使用事务,需要手动打开连接
// 连接对象开启事务
//开始事务
using (SqlTransaction trans = conn.BeginTransaction())
{
try
{
int result = conn.Execute(sql, productTypeList, trans);
//提交事务(持久化数据)
trans.Commit();
if (result > 0)
{
Console.WriteLine($”新增多条数据,带事务–添加{result}条成功!”);
}
}
catch (Exception ex)
{
//事务回滚
trans.Rollback();
Console.WriteLine(ex.Message);
}
}
}
}

 

执行存储过程 3个方法
1.查询产品表,根据类型ID 查询出所有产品,且返回产品数量
/// <summary>
/// 查询产品表,根据类型ID 查询出所有产品,且返回产品数量
/// </summary>
public static void PROC_Product_CountAndList()
{

using (SqlConnection conn = new SqlConnection(connStr))//打开数据库方式交给框架执行
{
//参数
DynamicParameters paras = new DynamicParameters();
paras.Add(“@typeID”, 1);//输入参数
paras.Add(“@count”, 0, DbType.Int32, ParameterDirection.Output);//输出参数

List<Product> productList = conn.Query<Product>(“PROC_Product”, paras, commandType: CommandType.StoredProcedure).ToList();//sql 存储过程

int count = paras.Get<int>(“@count”);//获取输出参数

Console.WriteLine($”共计:{count}”);
foreach (Product product in productList)
{
Console.WriteLine($”ID:{product.ID} – Name:{product.Name} – TypeID:{product.TypeID}”);
}
}
}
sql
–【存储过程】查询产品表,根据类型ID 查询出所有产品,且返回产品数量
create proc PROC_Product
@typeID int,
@count int out
as
begin

select @count=COUNT(ID) from Product where TypeID=@typeID;

select * from Product where TypeID=@typeID;
end
GO

–查询
DECLARE @count int
EXEC PROC_Product 1,@count OUTPUT
select @count
2.插入新产品的存储过程,产品名存在就不插入
/// <summary>
/// 插入新产品的存储过程,产品名存在就不插入
/// 参考:https://www.cnblogs.com/wyy1234/p/9078859.html
/// </summary>
public static void PROC_Product_insert()
{
using (SqlConnection conn = new SqlConnection(connStr))//打开数据库方式交给框架执行
{
//参数
DynamicParameters paras = new DynamicParameters();
paras.Add(“@name”, “苹果3”);//输入参数
paras.Add(“@typeID”, 1);//输入参数
paras.Add(“@count”, 0, DbType.Int32, ParameterDirection.Output);//输出参数

var result = conn.Query<Product>(“PROC_Product_insert”, paras, commandType: CommandType.StoredProcedure).ToList();//sql 存储过程

int count = paras.Get<int>(“@count”);//获取输出参数

Console.WriteLine($”插入:{count}条”);

}
}
sql
GO
–【存储过程】插入新产品的存储过程,产品名存在就不插入
create proc PROC_Product_insert
@name nvarchar(50),
@typeID int ,
@count int out
as
begin
declare @c int;
select @c=COUNT(ID) from Product where Name=@name;
if(@c!=0)
set @count =0;
else
begin
insert into Product(name, typeID) values(@name,@typeID);
set @count=1;
end
end
GO

–查询
DECLARE @count int
EXEC PROC_Product_insert “苹果手机2”,1,@count OUTPUT
select @count
3.获取产品表和产品类型表中的所有数据
/// <summary>
/// 获取产品表和产品类型表中的所有数据
/// 参考:https://www.cnblogs.com/wyy1234/p/9078859.html
/// </summary>
public static void PROC_TypeAndProduct()
{
using (SqlConnection conn = new SqlConnection(connStr))//打开数据库方式交给框架执行
{

//获取多个结果集
Dapper.SqlMapper.GridReader res = conn.QueryMultiple(“PROC_TypeAndProduct”, commandType: CommandType.StoredProcedure);

//注意:如果存储过程首先查出是Type,其次是Product,那么你在执行下面代码的时候顺序必须和存储过程查询顺序一致
//read方法获取Type和Product
IEnumerable<Type> typeList = res.Read<Type>();
IEnumerable<Product> productList = res.Read<Product>();
}
}
sql
GO
–【存储过程】获取产品表和产品类型表中的所有数据
create procedure PROC_TypeAndProduct
as
begin
select TypeID,TypeName from [Type];
select ID,TypeID,Name from Product;
end

–查询
EXEC PROC_TypeAndProduct

————————————————
版权声明:本文为CSDN博主「橙-极纪元」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/cplvfx/article/details/109849118