インスタンス データ プロパティを逆シリアル化する方法
ユーザーまたはワークフロー管理者は、永続化されたワークフロー インスタンスの状態を手動で調べることが必要になる場合があります。 SqlWorkflowInstanceStore は、次の 4 列を公開するインスタンス テーブルに関するビューを提供します。
- ReadWritePrimitiveDataProperties
- WriteOnlyPrimitiveDataProperties
- ReadWriteComplexDataProperties
- WriteOnlyComplexDataProperties
プリミティブ データ プロパティは、.NET型が「一般的」と見なされるプロパティ (Int32やStringなど) を参照し、複合データ プロパティは他のすべての型を参照します。 プリミティブ型の正確な列挙については、後で示すコード例を参照してください。
Read/write プロパティは、インスタンスが読み込まれるときにワークフロー ランタイムに戻されるプロパティを表します。 WriteOnly プロパティは、データベースに書き込まれた後に再度読み取られることはありません。
この例では、プリミティブ データ プロパティを逆シリアル化できるコードを示します。 ReadWritePrimitiveDataProperties または WriteOnlyPrimitiveDataProperties 列からバイト配列が読み取られることを前提として、このコードはバイナリ ラージ オブジェクト (BLOB) を、キー/値の各ペアがプロパティ名と対応する値を表す <XName, object>
型の Dictionary<TKey,TValue> に変換します。
重要
Microsoft では、使用可能な最も安全な認証フローを使用することをお勧めします。 Azure SQL に接続する場合は、Azure リソースの管理 ID が推奨される認証方法です。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.IO.Compression;
using System.Xml.Linq;
using System.Xml;
using System.Globalization;
using System.Data.SqlClient;
namespace PropertyReader
{
class Program
{
const string ConnectionString = @"Data Source=localhost;Initial Catalog=Persistence;Integrated Security=True;Asynchronous Processing=True";
static void Main(string[] args)
{
string queryString = "SELECT TOP 10 * FROM [System.Activities.DurableInstancing].[Instances]";
using (SqlConnection connection =
new SqlConnection(ConnectionString))
{
SqlCommand command =
new SqlCommand(queryString, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
byte encodingOption;
while (reader.Read())
{
if (reader["ReadWritePrimitiveDataProperties"] != DBNull.Value)
{
encodingOption = (byte)reader["EncodingOption"];
Console.WriteLine("Printing the ReadWritePrimitiveDataProperties of the instance with Id:" + reader["InstanceId"]);
foreach (KeyValuePair<XName, object> pair in (Dictionary<XName, object>)ReadDataProperties((byte[])reader["ReadWritePrimitiveDataProperties"], encodingOption))
{
Console.WriteLine("{0}, {1}" , pair.Key, pair.Value);
}
Console.WriteLine();
}
if (reader["WriteOnlyPrimitiveDataProperties"] != DBNull.Value)
{
encodingOption = (byte)reader["EncodingOption"];
Console.WriteLine("Printing the WriteOnlyPrimitiveDataProperties of the instance with Id:" + reader["InstanceId"]);
foreach (KeyValuePair<XName, object> pair in (Dictionary<XName, object>)ReadDataProperties((byte[])reader["WriteOnlyPrimitiveDataProperties"], encodingOption))
{
Console.WriteLine("{0}, {1}", pair.Key, pair.Value);
}
Console.WriteLine();
}
}
// Call Close when done reading.
reader.Close();
}
Console.ReadLine();
}
static Dictionary<XName, object> ReadDataProperties(byte[] serializedDataProperties, byte encodingOption)
{
if (serializedDataProperties != null)
{
Dictionary<XName, object> propertyBag = new Dictionary<XName, object>();
bool isCompressed = (encodingOption == 1);
using (MemoryStream memoryStream = new MemoryStream(serializedDataProperties))
{
// if the instance state is compressed using GZip algorithm
if (isCompressed)
{
// decompress the data using the GZip
using (GZipStream stream = new GZipStream(memoryStream, CompressionMode.Decompress))
{
// create an XmlReader object and pass it on to the helper method ReadPrimitiveDataProperties
using (XmlReader reader = XmlDictionaryReader.CreateBinaryReader(stream, XmlDictionaryReaderQuotas.Max))
{
// invoke the helper method
ReadPrimitiveDataProperties(reader, propertyBag);
}
}
}
else
{
// if the instance data is not compressed
// create an XmlReader object and pass it on to the helper method ReadPrimitiveDataProperties
using (XmlReader reader = XmlDictionaryReader.CreateBinaryReader(memoryStream, XmlDictionaryReaderQuotas.Max))
{
// invoke the helper method
ReadPrimitiveDataProperties(reader, propertyBag);
}
}
return propertyBag;
}
}
return null;
}
// Reads the primitive data properties from the XML stream.
// Invoked by the ReadDataProperties method.
static void ReadPrimitiveDataProperties(XmlReader reader, Dictionary<XName, object> propertyBag)
{
const string xmlElementName = "Property";
if (reader.ReadToDescendant(xmlElementName))
{
do
{
// get the name of the property
reader.MoveToFirstAttribute();
string propertyName = reader.Value;
// get the type of the property
reader.MoveToNextAttribute();
PrimitiveType type = (PrimitiveType)Int32.Parse(reader.Value, CultureInfo.InvariantCulture);
// get the value of the property
reader.MoveToNextAttribute();
object propertyValue = ConvertStringToNativeType(reader.Value, type);
// add the name and value of the property to the property bag
propertyBag.Add(propertyName, propertyValue);
}
while (reader.ReadToNextSibling(xmlElementName));
}
}
// Invoked by the ReadPrimitiveDataProperties method.
// Given a property value as parsed from an XML attribute, and the .NET Type of the Property, recreates the actual property value
// (e.g. Given a property value of "1" and a PrimitiveType of Int32, this method returns an object of type Int32 with value 1).
static object ConvertStringToNativeType(string value, PrimitiveType type)
{
switch (type)
{
case PrimitiveType.Bool:
return XmlConvert.ToBoolean(value);
case PrimitiveType.Byte:
return XmlConvert.ToByte(value);
case PrimitiveType.Char:
return XmlConvert.ToChar(value);
case PrimitiveType.DateTime:
return XmlConvert.ToDateTime(value, XmlDateTimeSerializationMode.RoundtripKind);
case PrimitiveType.DateTimeOffset:
return XmlConvert.ToDateTimeOffset(value);
case PrimitiveType.Decimal:
return XmlConvert.ToDecimal(value);
case PrimitiveType.Double:
return XmlConvert.ToDouble(value);
case PrimitiveType.Float:
return float.Parse(value, CultureInfo.InvariantCulture);
case PrimitiveType.Guid:
return XmlConvert.ToGuid(value);
case PrimitiveType.Int:
return XmlConvert.ToInt32(value);
case PrimitiveType.Long:
return XmlConvert.ToInt64(value);
case PrimitiveType.SByte:
return XmlConvert.ToSByte(value);
case PrimitiveType.Short:
return XmlConvert.ToInt16(value);
case PrimitiveType.String:
return value;
case PrimitiveType.TimeSpan:
return XmlConvert.ToTimeSpan(value);
case PrimitiveType.Type:
return Type.GetType(value);
case PrimitiveType.UInt:
return XmlConvert.ToUInt32(value);
case PrimitiveType.ULong:
return XmlConvert.ToUInt64(value);
case PrimitiveType.Uri:
return new Uri(value);
case PrimitiveType.UShort:
return XmlConvert.ToUInt16(value);
case PrimitiveType.XmlQualifiedName:
return new XmlQualifiedName(value);
case PrimitiveType.Null:
case PrimitiveType.Unavailable:
default:
return null;
}
}
// .NET Types that SQL Workflow Instance Store considers to be Primitive. Any other .NET type not listed in this enumeration is a "Complex" property.
enum PrimitiveType
{
Bool = 0,
Byte,
Char,
DateTime,
DateTimeOffset,
Decimal,
Double,
Float,
Guid,
Int,
Null,
Long,
SByte,
Short,
String,
TimeSpan,
Type,
UInt,
ULong,
Uri,
UShort,
XmlQualifiedName,
Unavailable = 99
}
}
}
複合データ プロパティを逆シリアル化する操作はサポートされていないので、この例ではその方法は示しません。
.NET