如何从SQL Server 2000 TEXT列中的C#String存储UTF-8字节

我有一个现有的SQL Server 2000数据库,它在文本列中存储文本的UTF-8表示。 我没有选择修改列的类型,并且必须能够将来自C#程序的非ASCII Unicode数据存储到该列中。

这是代码:

sqlcmd.CommandText = "INSERT INTO Notes " + "(UserID, LocationID, Note) " + "VALUES (" + Note.UserId.ToString() + ", " + Note.LocationID.ToString() + ", " + "@note); " + "SELECT CAST(SCOPE_IDENTITY() AS BIGINT) "; SqlParameter noteparam = new SqlParameter( "@note", System.Data.SqlDbType.Text, int.MaxValue ); 

在这一点上,我尝试了几种不同的方法将我的UTF-8数据放入参数中。 例如:

 // METHOD ONE byte[] bytes = (byte[]) Encoding.UTF8.GetBytes( Note.Note ); char[] characters = bytes.Select( b => (char) b ).ToArray(); noteparam.Value = new String( characters ); 

我也尝试过

 // METHOD TWO noteparam.Value = Note.Note; 

 // METHOD THREE byte[] bytes = (byte[]) Encoding.UTF8.GetBytes( Note.Note ); noteparam.Value = bytes; 

继续,这是代码的其余部分:

 sqlcmd.Parameters.Add( noteparam ); sqlcmd.Prepare(); try { Note.RecordId = (Int64) sqlcmd.ExecuteScalar(); } catch { return false; } 

方法一(将UTF8字节转换为字符串)做了一些奇怪的事情 – 我认为它是第二次对字符串进行UTF-8编码。

方法二存储垃圾。

方法三在ExecuteScalar()中抛出exception,声称它无法将参数转换为String。

我已经知道的事情,所以不需要告诉我:

  • SQL Server 2000已经过了/即将结束
  • TEXT列不适用于Unicode文本
  • 说真的,SQL Server 2000已经过时了。 你需要升级。

有什么建议?

如果数据库排序规则是SQL_Latin1_General_CP1(美国版SQL Server 2000的默认设置),则可以使用以下技巧将Unicode文本作为UTF-8存储在charvarchartext列中:

 byte[] bytes = Encoding.UTF8.GetBytes(Note.Note); noteparam.Value = Encoding.GetEncoding(1252).GetString(bytes); 

稍后,当您想要回读文本时,请反转该过程:

 SqlDataReader reader; // ... byte[] bytes = Encoding.GetEncoding(1252).GetBytes((string)reader["Note"]); string note = Encoding.UTF8.GetString(bytes); 

如果数据库排序规则不是 SQL_Latin1_General_CP1,则需要使用正确的代码页替换1252。

注意:如果查看企业管理器或查询分析器中存储的文本,您将看到代替非ASCII文本的奇怪字符,就像您在不支持Unicode的文本编辑器中打开UTF-8文档一样。

工作原理:将Unicode文本存储在非Unicode列中时,SQL Server会自动将文本从Unicode转换为数据库排序规则指定的代码页。 目标代码页中不存在的任何Unicode字符都将被不可逆转地破坏,这就是为什么前两种方法不起作用的原因。

但是你用方法一走上了正轨。 缺少的步骤是通过使用Windows-1252代码页将原始UTF-8字节转换为Unicode来“保护”原始UTF-8字节。 现在,当SQL Server执行从Unicode到Windows-1252的自动转换时,它会恢复原始的UTF-8字节。