序列化的db列仅返回文本字段的一部分

时间:2015-08-25 18:06:33

标签: .net sqlite protobuf-net

我目前有一个包含两个TEXT列的表。其中一列是使用Protobuf-net的序列化对象,似乎可以很好地插入到表中(在记事本中检查sqlite文件)。我的问题是当我检索这个TEXT项时,它只返回TEXT的前半部分!

这怎么可能发生?

我的代码:

public void save(SQLiteConnection m_dbConnection, Day day)
{
  using (MemoryStream stream = new MemoryStream())
  {
    Serializer.Serialize<Day>(stream, day);


    stream.Position = 0;
    StreamReader sr = new StreamReader(stream);
    string data = sr.ReadToEnd();
    string sql = "INSERT INTO mytable (date, data) VALUES (@date, @data)";
    SQLiteCommand command = new SQLiteCommand(sql, m_dbConnection);
    command.CommandType = System.Data.CommandType.Text;
    command.Parameters.Add(new SQLiteParameter("@date", day.getSqlDate()));
    command.Parameters.Add(new SQLiteParameter("@data", data));
    command.ExecuteNonQuery();
  }
}

public Day retrieve(SQLiteConnection m_dbConnection)
{
  string sql = "SELECT * FROM mytable ORDER BY date desc";
  SQLiteCommand command = new SQLiteCommand(sql, m_dbConnection);
  SQLiteDataReader reader = command.ExecuteReader();

  string str = "";
  while (reader.Read())
  {
    //HERE: Only first half of the serialized object
    str = reader["data"].ToString();
    using (Stream stream = GenerateStreamFromString(str))
    {
      return Serializer.Deserialize<Day>(stream);
    }
  }
  return null;
}

public Stream GenerateStreamFromString(string s)
{
  MemoryStream stream = new MemoryStream();
  StreamWriter writer = new StreamWriter(stream);
  writer.Write(s);
  writer.Flush();
  stream.Position = 0;
  return stream;
}

编辑:感谢@Hari Nair,我发现它正在突破某个角色。这是字符 ,但我不知道如何清理这个字符串,因此它是SQL安全的。有什么想法吗?

注意:我试图在没有运气的情况下替换\ n和\ r \ n,并且无法弄清楚角色是什么。

2 个答案:

答案 0 :(得分:1)

您可以检查文本是否在任何特殊字符处中断。 (就像一个双引号?)如果是,在插入过程中逃避它们。

(这不值得回答,但我没有足够的声誉来评论)

答案 1 :(得分:1)

串行器的输出是二进制的。我不知道你正在使用什么列类型,但如果它是文本,它可能会咳嗽二进制数据也就不足为奇了。如果二进制数据包含NUL(ASCII 0),则.NET中的几乎所有内容都将其视为字符串终止字符,从而截断。我敢打赌,如果你偷看了char数组,你会看到0它停在哪里。

您可以将列类型更改为适合存储二进制数据的列类型,或将输出数据编码为类似Base64字符串的类型:

你没有语言标签,所以这是VB,如果你需要它我会修改为C#:

' test string
Dim strFoo = "this is a string"
Dim strB64 As String = ""

Using ms As New MemoryStream()
    ms.Position = 0
    Serializer.Serialize(Of String)(ms, strFoo)

    ' convert binary output to character string
    strB64 = Convert.ToBase64String(ms.ToArray())
End Using

' what a Base64 looks like
Console.WriteLine("Encoded data: {0}", strB64)

' simple test to check the round trip (and what you'll need
' to do when getting the data from the DB):
Dim newFoo As String = ""
Using ms As New MemoryStream(Convert.FromBase64String(strB64))

    newFoo = Serializer.Deserialize(Of String)(ms)
    Console.WriteLine(newFoo)
End Using

输出:

  

编码数据:ChB0aGlzIGlzIGEgc3RyaW5n
  这是一个字符串