ADO.NET笔记——存储二进制大对象(BLOB)
相关知识
上传二进制大对象(Binary Large Object)(如图片、视频等)的基本编程步骤是:
- 在数据库中使用varbinary(MAX)、varchar(MAX)或者nvarchar(MAX)等数据类型记录BLOB
- 使用INSERT INTO语句,在表中建立一个新行
- 使用 UPDATE xxx.WRITE 语句,逐段将BLOB写入大数据字段中
代码示例
- 数据库:沿用AccountDBforSQLInjection,使用下列的SQL语句建立一个包含varbinary(MAX)字段类型的表:
CREATE TABLE [dbo].[Photo](
[PhotoID] [int] IDENTITY(1,1) NOT NULL,
[PhotoName] [nvarchar](50) NULL,
[PhotoData] [varbinary](max) NULL,
CONSTRAINT [PK_Photo] PRIMARY KEY CLUSTERED
(
[PhotoID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]该表的主键PhotoID是自增长列
- SQL语句定义:
static string strConn = @"server=Joe-PC;database=AccountDBforSQLInjection;uid=sa;pwd=root";
//以下SQL命令在Photo表中创建一个新行,并且返回新行的PhotoID(该字段是自增长的)
//PhotoData不能初始化为NULL,因为.WRITE字句无法在NULL字段上操作
static string strInsertCmd = @"INSERT INTO Photo(PhotoName, PhotoData) Values(@PhotoID, 1);SELECT @PhotoID=@@IDENTITY";
//@@identity的作用是返回最后插入的标识值,使用它来获取插入数据后的标识符。
//但有一点是需要注意的,@@identity返回的是最后的标识符,所以,要想正确的返回插入后的标识符,那么就必须保证,你想要的结果是最后的标识符,否则就会隐藏bug。//以下SQL语句用于更新PhotoData字段中的一部分数据
//@data表示待写入的数据,@offset表示在该字段的哪个位置开始写起,@length表示写入多少个字节
static string strUploadCmd = @"UPDATE Photo SET PhotoData.WRITE(@data, @offset, @length) WHERE PhotoID=@PhotoID"; - 创建新行:
// 在图片表中创建新行
static int InsertPhoto()
{
using (SqlConnection conn = new SqlConnection(strConn))
{
conn.Open();
SqlCommand cmd = new SqlCommand(strInsertCmd, conn);
cmd.Parameters.Add("@PhotoName", SqlDbType.NVarChar, ).Value = "flower.jpg";
SqlParameter id = cmd.Parameters.Add("@PhotoID", SqlDbType.Int);
id.Direction = ParameterDirection.Output;
cmd.ExecuteNonQuery();
return Convert.ToInt32(id.Value);
}
} - 向新行中写入图片数据:
//从磁盘文件读入图片数据,然后逐段写入数据库
static void UploadPhoto(int photoID)
{
using (SqlConnection conn = new SqlConnection(strConn))
{
SqlCommand cmd = new SqlCommand(strUploadCmd, conn);
cmd.Parameters.Add("@PhotoID", SqlDbType.Int).Value = photoID;
SqlParameter data = cmd.Parameters.Add("@data", SqlDbType.VarBinary, -);
SqlParameter offset = cmd.Parameters.Add("@offset", SqlDbType.Int);
offset.Value = ;
SqlParameter length = cmd.Parameters.Add("@length", SqlDbType.Int); int BUF_SIZE = ;
string fileName = "..\\..\\picture.jpg"; FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
byte[] buf = new byte[BUF_SIZE];
int read = fs.Read(buf, , BUF_SIZE);
conn.Open(); while (read > )
{
length.Value = read;
data.Value = buf;
cmd.ExecuteNonQuery();
offset.Value = Convert.ToInt32(offset.Value) + read;//偏移量逐次递进
read = fs.Read(buf, , BUF_SIZE);
} fs.Close();
}
} - 下载图片数据,检测上传是否成功:
//将前述写入的图片从数据库读出来,保存到文件中
static void DownloadPhoto(int photoID)
{
using (SqlConnection conn = new SqlConnection(strConn))
{
string strCmd = "select * From photo where PhotoID=" + photoID.ToString();
SqlCommand cmd = new SqlCommand(strCmd, conn);
conn.Open();
SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.SequentialAccess);
dr.Read();
FileStream fs = new FileStream("..\\..\\savedpicture.jpg", FileMode.OpenOrCreate, FileAccess.Write);
byte[] buf = new byte[];
long bytesRead = ;
long startIndex = ;
while ((bytesRead = dr.GetBytes(, startIndex, buf, , )) > )
{
fs.Write(buf, , (int)bytesRead);
startIndex += bytesRead;
}
fs.Close();
}
} - 主函数:
static void Main(string[] args)
{
int photoID = InsertPhoto();
UploadPhoto(photoID);
DownloadPhoto(photoID);
}
程序说明
本程序将从项目文件夹上传picture.jpg文件至数据库,然后又从数据库中下载数据保存为savedpicture.jpg文件,以便检查上传是否成功
ADO.NET笔记——存储二进制大对象(BLOB)的更多相关文章
- ADO.NET笔记——读取二进制大对象(BLOB)
相关知识: 在SQL Server中,一般情况下,每行数据的总长度不能超过8K字节.因此,下列数据类型的长度,也不能超过8K字节:binary,char(),nchar(),varchar(),nva ...
- 3.2 配置构建Angular应用——简单的笔记存储应用
本节我们会通过构建一个简单的笔记存储应用(可以载入并修改一组简单的笔记)来学习如何应用Angular的特性.这个应用用到的特性有: 在JSON文件中存储笔记 展示.创建.修改和删除笔记 在笔记中使用M ...
- memcached学习笔记——存储命令源码分析下篇
上一篇回顾:<memcached学习笔记——存储命令源码分析上篇>通过分析memcached的存储命令源码的过程,了解了memcached如何解析文本命令和mencached的内存管理机制 ...
- memcached学习笔记——存储命令源码分析上篇
原创文章,转载请标明,谢谢. 上一篇分析过memcached的连接模型,了解memcached是如何高效处理客户端连接,这一篇分析memcached源码中的process_update_command ...
- ADO学习笔记之注入漏洞与参数化查询
ADO学习笔记之注入漏洞与参数化查询 作为新手,在学习ADO程序时,使用 sql 语言查询数据时,很容易写类似如下代码: using (SqlConnection con = new SqlConne ...
- 3.2.1 配置构建Angular应用——简单的笔记存储应用——编辑功能
本节我们会接着上节课的内容,继续来完成使用Angular来创建简单的笔记存储应用,上一节课,我们完成了笔记的展示功能,本节课,我们来完成编辑功能. 编辑主要是两个功能:编辑现有的笔记以及创建新笔记.首 ...
- 3.2.1 配置构建Angular应用——简单的笔记存储应用——展示功能
本节我们会通过构建一个简单的笔记存储应用(可以载入并修改一组简单的笔记)来学习如何应用Angular的特性.这个应用用到的特性有: 在JSON文件中存储笔记 展示.创建.修改和删除笔记 在笔记中使用M ...
- 【mysql】关于InnoDB存储引擎 text blob 大字段的存储和优化
最近在数据库优化的时候,看到一些表在设计上使用了text或者blob的字段,单表的存储空间已经达到了近100G,这种情况再去改变和优化就非常难了 一.简介 为了清楚大字段对性能的影响,我们必须要知道i ...
- ADO.net笔记
1.DbConnectionConnection对象也称为数据库连接对象,Connection对象的功能是负责对数据源的连接.所有Connection对象的基类都是DbConnection类.Conn ...
随机推荐
- Python编码相关文章推荐
Table of Contents 1. 分享 分享 python2里面编码对很多人来说是个很头疼的问题,今天分享一篇编码相关的文章,是前几天读到的相比于大部分解释编码问题的一知半解模糊不清,这篇写得 ...
- LeetCode40 Combination Sum II
题目: Given a collection of candidate numbers (C) and a target number (T), find all unique combination ...
- 浅析SQL Server 2005中的主动式通知机制
一.引言 在开发多人同时访问的Web应用程序(其实不只这类程序)时,开发人员往往会在缓存策略的设计上狠下功夫.这是因为,如果将这种环境下不常变更的数据临时存放在应用程序服务器或是用户机器上的话,可以避 ...
- c#获得目标服务器中所有数据库名、表名、列名的实现代码
/// <summary> /// 获得目标服务器所有数据库名 /// </summary> /// <param name="serverName" ...
- 快递鸟顺丰电子面单接口API-JAVA
一.电子面单对接案例 1.接口描述 接口支持的消息接收方式:HTTP POST 请求方法的编码格式(utf-8):"application/x-www-form-urlencoded;cha ...
- SolrEntityProcessor
SolrEntityProcessor从不同的solr实例和内核中引入数据,这个数据是基于指定的或者是过滤的查询来获取到的.如果你需要复制索引,并且小幅度的修改目标索引文件中的数据,那么可以使用Sol ...
- ProgressBar的Indeterminate属性
Indeterminate ProgressBar默认是白色的,如果容器的背景也是白色的,这样就根本看不到Progressbar. 简单解决方案: 用style属性设定反转的颜色. <Progr ...
- IOS 设置定时器
IOS 设置定时器 自动滚动视图 定时发送坐标信息 即时显示 时钟 NSTimer *timer; - (void)start {//1second 调用一次 timer = [NSTimer sc ...
- 【¥200代金券、iPad等您来拿】 阿里云9大产品免费公测#10月9日-11月6日#
#10.09-11.06#200元代金券.iPad大奖, 9大产品评测活动! 亲爱的阿里云小伙伴们: 云产品的多样性(更多的云产品)也是让用户深度使用云计算的关键.今年阿里云产品线越来越丰富,小云搜罗 ...
- 《算法导论》习题解答 Chapter 22.1-6(求universal sink 通用汇点)
思路:设置两个游标i指向行,j指向列,如果arr[i][j]==1,则i=max{i+1,j},j++:如果arr[i][j]==0,则j=max{i+1,j+1}. 伪代码: has_univers ...