使用EF Core/dapper/sqlclient基础知识
学习如何使用Dapper,Entity Framework Core和SqlClient数据提供商读取和插入图像中的图像。
对于新手甚至中级开发人员,使用图像的开发人员可能是一项艰巨的任务,因为他们要么编写代码,期望它立即工作,而无需对使用适当的数据类型或从Internet复制粘贴代码而不更改太多的内容。并期望代码工作。
要吸引主要受众,使用了三种不同的方法,dapper,ef core和sqlclient数据提供商。
使用正确的数据类型
没有使用图像经验的开发人员会选择图像经文Varbinary(Max)未意识到图像类型的开发人员最有可能在SQL-Server的将来版本中删除。这意味着,不要使用图像,而是使用varbinary(max)。
代码样本的列定义
操作
所使用的三种方法既将插入并读取单个记录。
重要的是:
- Dapper和EF Core需要更少的手写代码
- dapper和sqlclient需要SQL语法的体面知识
- ef核心,在这种情况下是使用EF Power Tools配置的,这意味着没有手动配置。
- 哪个是个人选择
插入新的记录版本1
在以下样本中插入记录,但我们没有获得新的记录键
使用SQLClient数据提供商插入新记录
插入新记录。
- 使用连接字符串创建连接对象
- 创建命令对象
- 添加一个参数
- 打开连接
- 执行命令
public static void InsertImage(byte[] imageBytes)
{
var sql = "INSERT INTO [dbo].[Pictures1] ([Photo]) VALUES (@ByteArray)";
using var cn = new SqlConnection(ConnectionString());
using var cmd = new SqlCommand(sql, cn);
cmd.Parameters.Add("@ByteArray", SqlDbType.VarBinary).Value = imageBytes;
cn.Open();
cmd.ExecuteNonQuery();
}
与Dapper插入新记录
- 使用连接字符串创建连接对象
- 添加一个参数
- 执行命令
public static void InsertImage(byte[] imageBytes)
{
var sql = "INSERT INTO [dbo].[Pictures1] ([Photo]) VALUES (@ByteArray)";
using var cn = new SqlConnection(ConnectionString());
var parameters = new { ByteArray = imageBytes};
cn.Execute(sql, parameters);
}
用EF Core 7插入新记录
- 创建DBContext的实例
- 创建一个类型的实例
- 保存更改
public static void InsertImage(byte[] imageBytes)
{
using var context = new Context();
context.Add(new Pictures() { Photo = imageBytes });
context.SaveChanges();
}
插入新的记录版本2
在以下样本中,使用新记录主键
插入记录sqlclient
我们将SELECT CAST(scope_identity() AS int)
附加到插入物,而不是ExecuteNonQuery
使用返回对象的ExecuteScalar
,我们将其铸造为与主键相同的类型。
public static void InsertImage(byte[] imageBytes)
{
var sql =
"""
INSERT INTO [dbo].[Pictures1] ([Photo]) VALUES (@ByteArray);
SELECT CAST(scope_identity() AS int);
""";
using var cn = new SqlConnection(ConnectionString());
using var cmd = new SqlCommand(sql, cn);
cmd.Parameters.Add("@ByteArray", SqlDbType.VarBinary).Value = imageBytes;
cn.Open();
var key = (int)cmd.ExecuteScalar();
}
Dapper
以下OUTPUT Inserted.Id
添加到SQL中,注意Id
需要匹配主密钥名称。
而不是Execute
方法,我们使用的ExecuteScalar
基本上与sqlclient相同。
public static void InsertImage(byte[] imageBytes)
{
var sql = "INSERT INTO [dbo].[Pictures1] ([Photo]) OUTPUT Inserted.Id VALUES (@ByteArray) ";
using var cn = new SqlConnection(ConnectionString());
var parameters = new { ByteArray = imageBytes};
var key = (int)cn.ExecuteScalar(sql, parameters);
}
EF核心
只需将图片对象移至变量即可。在Savechanges之后,photoContainer.Id
将具有新的主键。
public static void InsertImage(byte[] imageBytes)
{
using var context = new Context();
var photoContainer = new Pictures() { Photo = imageBytes };
context.Add(photoContainer);
context.SaveChanges();
}
阅读图像
您会注意到的是,在这三种方法之间,它们实际上是相同的。
使用EF核心,还有一些额外的行与返回类型保持同步,以使其他两种方法。
SQLClient具有比其他两种方法多几行代码。
sqlclient
public static (PhotoContainer container, bool success) ReadImage(int identifier)
{
var photoContainer = new PhotoContainer() { Id = identifier };
var sql = "SELECT id, Photo FROM dbo.Pictures1 WHERE dbo.Pictures1.id = @id;";
using var cn = new SqlConnection(ConnectionString());
using var cmd = new SqlCommand(sql, cn);
cmd.Parameters.Add("@Id", SqlDbType.Int).Value = identifier;
cn.Open();
var reader = cmd.ExecuteReader();
reader.Read();
if (!reader.HasRows)
{
return (null, false);
}
var imageData = (byte[])reader[1];
using (var ms = new MemoryStream(imageData, 0, imageData.Length))
{
ms.Write(imageData, 0, imageData.Length);
photoContainer.Picture = Image.FromStream(ms, true);
}
return (photoContainer, true);
}
dapper
public static (PhotoContainer container, bool success) ReadImage(int identifier)
{
var photoContainer = new PhotoContainer() { Id = identifier };
var sql = "SELECT id, Photo FROM dbo.Pictures1 WHERE dbo.Pictures1.id = @id";
using var cn = new SqlConnection(ConnectionString());
var parameters = new { id = identifier };
var container = cn.QueryFirstOrDefault<ImageContainer>(sql, parameters);
if (container is null)
{
return (null, false);
}
var imageData = container.Photo;
using (var ms = new MemoryStream(imageData, 0, imageData.Length))
{
ms.Write(imageData, 0, imageData.Length);
photoContainer.Picture = Image.FromStream(ms, true);
}
return (photoContainer, true);
}
ef core
public static (PhotoContainer container, bool success) ReadImage(int identifier)
{
var photoContainer = new PhotoContainer() { Id = identifier };
using var context = new Context();
var item = context.Pictures1.FirstOrDefault(item => item.Id == identifier);
if (item is null)
{
return (null, false);
}
var imageData = item.Photo;
using (var ms = new MemoryStream(imageData, 0, imageData.Length))
{
ms.Write(imageData, 0, imageData.Length);
photoContainer.Picture = Image.FromStream(ms, true);
}
return (photoContainer, true);
}
注意
由于代码正确编写,因此在任何代码中都没有例外处理,这不会通过任何方式实施您的代码中的异常处理,因为许多事情可能会出错,因此请实施异常处理
准备项目运行
使用文件夹脚本下的脚本,创建数据库,创建单个表并填充。
为什么您是Windows表单项目?
使用Windows表单项目绕过诸如Securty问题之类的事物,并且非常易于阅读和理解。