SilverlightでDataSet
SilverlightではDataSetがサポートされてい(DataSetやDataTableといったクラスがあり)ません。新規開発であれば、ADO.NET Data Servicesフレームワークや今後正式なリリースが予定されているWCF RIA Servicesを使う方法になるかと思いますが、既存資産の活用という観点ではSilverlightにもDataSetが欲しいところです。
2月10日にグレープシティから発売予定のComponentOne Studioに含まれるSilverlightコンポーネントでは、「C1.Silverlight.Data.dll」というアセンブリにおいてDataSet、DataTable、DataViewといったおなじみのクラスが提供されており、これらを利用することでDataSetを使った既存資産をSilverlightでもほぼそのまま活用することができます。
例えば、Windowsフォームで下記のようにコーディングしていたものは、
Windowsフォーム
// 変更をサーバーに確定させる
private void _btnCommit_Click(object sender, EventArgs e)
{
if (_ds != null)
{
// 変更状態ごとにバイト配列に格納します
byte dtAdded = GetChanges(DataRowState.Added);
byte dtModified = GetChanges(DataRowState.Modified);
byte dtDeleted = GetChanges(DataRowState.Deleted);
// サービスの呼び出し
var svc = GetDataService();
svc.UpdateData(dtAdded, dtModified, dtDeleted);
}
}
byte GetChanges(DataRowState state)
{
DataSet ds = _ds.GetChanges(state);
if (ds != null)
{
MemoryStream ms = new MemoryStream();
ds.WriteXml(ms);
return ms.ToArray();
}
return null;
}
private void _btnCommit_Click(object sender, EventArgs e)
{
if (_ds != null)
{
// 変更状態ごとにバイト配列に格納します
byte dtAdded = GetChanges(DataRowState.Added);
byte dtModified = GetChanges(DataRowState.Modified);
byte dtDeleted = GetChanges(DataRowState.Deleted);
// サービスの呼び出し
var svc = GetDataService();
svc.UpdateData(dtAdded, dtModified, dtDeleted);
}
}
byte GetChanges(DataRowState state)
{
DataSet ds = _ds.GetChanges(state);
if (ds != null)
{
MemoryStream ms = new MemoryStream();
ds.WriteXml(ms);
return ms.ToArray();
}
return null;
}
ComponentOne Studioの「C1.Silverlight.Data.dll」を使うことで、
Silverlight
// 変更をサーバーに確定させる
private void _btnCommit_Click(object sender, RoutedEventArgs e)
{
if (_ds != null)
{
// 変更状態ごとにバイト配列に格納します
byte dtAdded = GetChanges(DataRowState.Added);
byte dtModified = GetChanges(DataRowState.Modified);
byte dtDeleted = GetChanges(DataRowState.Deleted);
// サービスの呼び出し
var svc = GetDataService();
svc.UpdateDataCompleted += svc_UpdateDataCompleted;
svc.UpdateDataAsync(dtAdded, dtModified, dtDeleted);
}
}
byte GetChanges(DataRowState state)
{
DataSet ds = _ds.GetChanges(state);
if (ds != null)
{
MemoryStream ms = new MemoryStream();
ds.WriteXml(ms);
return ms.ToArray();
}
return null;
}
void svc_UpdateDataCompleted(object sender, UpdateDataCompletedEventArgs e)
{
if (!string.IsNullOrEmpty(e.Result))
{
throw new Exception("サーバーの更新中にエラーが発生しました。: " + e.Result);
}
_tbStatus.Text = "サーバーに変更が適用されました。";
_ds.AcceptChanges();
}
private void _btnCommit_Click(object sender, RoutedEventArgs e)
{
if (_ds != null)
{
// 変更状態ごとにバイト配列に格納します
byte dtAdded = GetChanges(DataRowState.Added);
byte dtModified = GetChanges(DataRowState.Modified);
byte dtDeleted = GetChanges(DataRowState.Deleted);
// サービスの呼び出し
var svc = GetDataService();
svc.UpdateDataCompleted += svc_UpdateDataCompleted;
svc.UpdateDataAsync(dtAdded, dtModified, dtDeleted);
}
}
byte GetChanges(DataRowState state)
{
DataSet ds = _ds.GetChanges(state);
if (ds != null)
{
MemoryStream ms = new MemoryStream();
ds.WriteXml(ms);
return ms.ToArray();
}
return null;
}
void svc_UpdateDataCompleted(object sender, UpdateDataCompletedEventArgs e)
{
if (!string.IsNullOrEmpty(e.Result))
{
throw new Exception("サーバーの更新中にエラーが発生しました。: " + e.Result);
}
_tbStatus.Text = "サーバーに変更が適用されました。";
_ds.AcceptChanges();
}
のようにSilverlightで書きなおすことができます。SilverlightではWebサービスの呼び出しが非同期に限られているため少しコーディング量が増えていますが、もしWindowsフォームでも非同期呼び出しを行っていればまったく同様となります。上記の部分で異なってくるとすれば、ボタンのClickイベントの引数がRoutedEventArgsになるくらいです。
この「C1.Silverlight.Data.dll」を使用したサンプルプロジェクトを下記の場所に置いておきます。
このサンプルプロジェクトは本日(1/27)に公開になったComponentOne Studioのトライアル版でもお試しいただけます。ぜひインストールして実際に触ってみてください。