Sql server 使用实体框架从SQL Server检索blob时出现编码问题
我注意到一个奇怪的现象,即尝试将2003 MS word文档存储在SQL Server blob(Sql server 使用实体框架从SQL Server检索blob时出现编码问题,sql-server,entity-framework,encoding,c#-3.0,Sql Server,Entity Framework,Encoding,C# 3.0,我注意到一个奇怪的现象,即尝试将2003 MS word文档存储在SQL Server blob(nvarchar(max))字段中,然后使用实体框架(EF1)检索它们,然后将它们转换回文件(然后附加到电子邮件) 基本代码: 1) 我使用openrowset将文档插入数据库: INSERT INTO [dbo].[Attachment]([id],[Blob]) SELECT 1, (SELECT BulkColumn FROM OPENROWSET(Bulk 'path_to_
nvarchar(max)
)字段中,然后使用实体框架(EF1)检索它们,然后将它们转换回文件(然后附加到电子邮件)
基本代码:
1) 我使用openrowset将文档插入数据库:
INSERT INTO [dbo].[Attachment]([id],[Blob])
SELECT 1, (SELECT BulkColumn FROM OPENROWSET(Bulk 'path_to_attachment\abc123.doc', SINGLE_BLOB) AS BLOB)
2) 然后,我使用EF1从数据库中检索该文件(为简洁起见,进行了简化-绕过repo等):
问题:
这是可行的,但是我注意到在这个过程中推送文件后,文件中出现了一些差异,一些小的格式问题等等
在进行了更深入的挖掘(使用VBinDiff)之后,看起来一些Unicode字符正在转换为FDFF
00DC > FDFF
原件:
00 00 00 DC 00 00 00
转换:
00 00 00 FD FF 00 00 00
其他例子包括:
BED9 > FDFF
CFD9 > FDFF
这看起来是从这里开始的范围中的最后一个:
问题
1) 在返回字符串对象attachment.Blob
-然后尝试将其转换回字节数组之前,我是在做一些愚蠢的事情,还是EF在做一些古怪的事情
2) 在仍然使用实体框架的情况下,有没有更好的方法从blob字段中检索出准确的字节?(或者我应该使用存储过程,或者使用SqlDataReader,而不是使用SqlDataReader—为了不使数据访问路径复杂化,我真的不想这样做)使用导入将文件的内容返回为varbinary(max)
类型的单行、单列行集
我建议使用将文件读取为nvarchar(max)
的SINGLE\u-BLOB
,而不是SINGLE\u-BLOB
必须使用此处显示的SINGLE\u NCLOB
选项读取Unicode文件:
SELECT BulkColumn
FROM OPENROWSET (BULK 'path_to_attachment\abc123.doc', SINGLE_NCLOB) AS BLOB
参考号:
更新(回应评论):如果文件不是unicode(如您尝试的那样),则在检索它们时,不应使用unicode编码来获取字节:
var bytes = Encoding.ASCII.GetBytes(attachment.Blob);
米奇的回答帮助我指出了代码中的错误。出于某种原因(我认为是习惯的力量),我会将Blob字段设置为
nvarchar(max)
,正如Mitch所指出的,SINGLE\u Blob
将文件信息保存为varbinary(max)
,这实际上是我在应用程序中想要的(请参见问题点2)
解决方案:
nvarchar(max)
转换为varbinary(max)
string
更改为二进制`var attachment = (from a in ctx.Attachment where a.id == 1 select a).FirstOrDefault()
var bytes = Encoding.Unicode.GetBytes(attachment.Blob);
var stream = new MemoryStream(bytes);
var fileName = "abc123.doc";
var fileToAttach = new Attachment(stream, fileName, MediaTypeNames.Application.Octet);
为此:
var attachment = (from a in ctx.Attachment where a.id == 1 select a).FirstOrDefault()
var stream = new MemoryStream(attachment.Blob);
var fileName = "abc123.doc";
var fileToAttach = new Attachment(stream, fileName, MediaTypeNames.Application.Octet);
@米奇·麦特:如果我尝试将参数更改为
SINGLE\u NCLOB
,我会收到错误消息:SINGLE\u NCLOB需要一个UNICODE(widechar)输入文件。指定的文件不是Unicode。
-非常感谢您的回复。
var attachment = (from a in ctx.Attachment where a.id == 1 select a).FirstOrDefault()
var stream = new MemoryStream(attachment.Blob);
var fileName = "abc123.doc";
var fileToAttach = new Attachment(stream, fileName, MediaTypeNames.Application.Octet);