コンパクトなフレームワークアプリケーションでprotobuf-net v1を使用して、オブジェクトをSQL Server CEデータベースに格納するためのシリアル化を処理しました。protobuf-netとsql server ce
は最近、我々は(我々は多くの種類をシリアル化していない場合は、エラーが消える。)により、非常に多くの種類を使用して明らかにバリケードを打っ参考:絶望でhttp://code.google.com/p/protobuf-net/issues/detail?id=50#c6
(私たちはすぐにリリースすることになっています)私たちはv2をダウンロードし、それを使用しています(シリアライザを事前にコンパイルせずに)。しかし、データをデシリアライズする際に、奇妙なエラーが発生することがあります。これは、未知のワイヤタイプ6と、int 32を読み込むエラーです。int型にキャストするとオーバーフローエラーが発生します。以前は同じメソッドを使用してシリアル化されていました...)私にはバイナリデータが破損しているように見えますが、SQL Serverサーバーのvarbinaryフィールドに格納して戻しています。
バイナリデータがどのように壊れる可能性がありますか?
いくつかの背景のためのMarcの答えをお読みください:
FINAL FIX(以下のコードを参照してください)。私が問題を伝えることができるのは、SetBinaryメソッドがどのように動作するかで、既存のデータを消去または切り捨てるようには見えないためです。つまり、保存されているバイナリデータが以前のデータよりも小さい場合、
私たちは、これを変更することにより、それを修正:これに
if (buffer.Length > 0)
{
record.SetBytes(insertSet.GetOrdinal(SerializedDataColumnName), 0, buffer, 0, buffer.Length);
}
:
if (buffer.Length > 0)
{
record.SetValue(insertSet.GetOrdinal(SerializedDataColumnName), null);
record.SetBytes(insertSet.GetOrdinal(SerializedDataColumnName), 0, buffer, 0, buffer.Length);
}
はありがとうございます。
UPDATE: コードDB(コードの提案は歓迎だけでなく、問題領域)にシリアル化するために使用:
command.CommandType = CommandType.TableDirect;
MemoryStream ms = null;
using (SqlCeResultSet insertSet = command.ExecuteResultSet(ResultSetOptions.Updatable))
{
foreach (var item in items)
{
ms = new MemoryStream();
Serializer.Serialize<T>(ms, item);
var record = insertSet.CreateRecord();
var buffer = ms.GetBuffer();
if (buffer.Length > 0)
{
record.SetBytes(insertSet.GetOrdinal(SerializedDataColumnName), 0, buffer, 0, buffer.Length);
}
else
{
record.SetValue(insertSet.GetOrdinal(SerializedDataColumnName), null);
}
insertSet.Update();
}
}
if (ms != null)
{
ms.Dispose();
}
コードをデシリアライズするために使用:
using (var ms = new MemoryStream())
{
using (SqlCeResultSet recordSet = command.ExecuteResultSet(ResultSetOptions.Scrollable))
{
//var serializer = null; //ServiceDepository.TryGetProvider<TypeModel, T>();
while (recordSet.Read())
{
if (!recordSet.IsDBNull(recordSet.GetOrdinal(SerializedDataColumnName)))
{
var count = recordSet.GetBytes(recordSet.GetOrdinal(SerializedDataColumnName), 0, null, 0, 1);
var bytes = new byte[count];
recordSet.GetBytes(recordSet.GetOrdinal(SerializedDataColumnName), 0, bytes, 0, (int)count);
if (bytes.Length > 0)
{
var ms2 = new MemoryStream(bytes);
item = Serializer.Deserialize<T>(ms2);
}
}
if (item == null)
{
//handle 'empty' items -- there were no properties
// that needed to be serialized
item = new T();
}
list.Add(item);
}
}
}
...さて、これは単なる問題の一部かもしれないが、我々は最初にそれを排除すべきです。 –
@Marc:これは問題の大きな部分です(なぜ、protobuf-netサイトにバグを登録するのではなく、ここに投稿しています)。それは無作為で、私は再現シナリオを決定することができませんでした。それがprotobuf-netエラーか、SQL Serverのバイナリストレージを使用する際の問題かどうかはわかりません。 – Steve
@Steveシノニティチェックできるようにシリアライゼーションコードを共有できますか? –