using System.Collections.Generic;
using System.Xml.Serialization;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO.Compression;
public string XmlSchema { get; set; }
public string XmlDiffGram { get; set; }
public static DataSetDTO FromDataSet(DataSet dataSet, bool indent = false)
var diffGram = new StringBuilder();
using (var xmlWriter = XmlWriter.Create(new StringWriter(diffGram), new XmlWriterSettings { Indent = indent }))
dataSet.WriteXml(xmlWriter, XmlWriteMode.DiffGram);
var schema = new StringBuilder();
using (var xmlWriter = XmlWriter.Create(new StringWriter(schema), new XmlWriterSettings { Indent = indent }))
dataSet.WriteXmlSchema(xmlWriter);
XmlSchema = schema.ToString(),
XmlDiffGram = diffGram.ToString(),
public DataSet ToDataSet()
var dataSet = new DataSet();
if (!string.IsNullOrEmpty(XmlSchema))
dataSet.ReadXmlSchema(new StringReader(XmlSchema));
if (!string.IsNullOrEmpty(XmlDiffGram))
using var reader = XmlReader.Create(new StringReader(XmlDiffGram));
dataSet.ReadXml(reader, XmlReadMode.DiffGram);
public static class DataExtensions
public static DataRowState [] GetRowStates(this DataTable table) =>
table.AsEnumerable().Select(r => r.RowState).ToArray();
public static (string name, DataRowState [] states) [] GetRowStates(this DataSet set) =>
set.Tables.Cast<DataTable>().Select(t => (t.TableName, t.GetRowStates())).ToArray();
public static void Test()
var set = CreateDataSet();
PopulateDataSet(set, 1, 3);
var row1 = set.Tables[0].Rows[0];
PopulateDataSet(set, 10, 3);
set.Tables[0].Rows[1]["Title"] = "My Modified Title";
Console.WriteLine("Input DataSet:");
Console.WriteLine(set.GetXml());
Console.WriteLine(string.Join(",", set.Tables[0].GetRowStates()));
TestRoundTrip(set, RoundTripViaBinary, nameof(RoundTripViaBinary));
Console.WriteLine($"Successfully round-tripped using {nameof(RoundTripViaBinary)}.\n");
TestRoundTrip(set, RoundTripViaXML, nameof(RoundTripViaXML));
Console.WriteLine($"Successfully round-tripped using {nameof(RoundTripViaXML)}.\n");
static void TestRoundTrip(DataSet set, Func<DataSet, DataSet> roundTrip, string name = "")
var newSet = roundTrip(set);
Assert.AreEqual(set.Tables.Count, newSet.Tables.Count, $"set.Tables.Count using {name}");
Assert.AreEqual(set.GetXml(), newSet.GetXml(), $"set.GetXml using {name}");
Assert.AreEqual(set.GetXmlSchema(), newSet.GetXmlSchema(), $"set.GetXmlSchema using {name}");
Assert.IsTrue(set.GetRowStates().Zip(newSet.GetRowStates()).All(p => p.Item1.name == p.Item2.name && p.Item1.states.SequenceEqual(p.Item2.states)), $"Row States identical using {name}");
static DataSet RoundTripViaXML(DataSet set)
var newSet = new DataSet();
using var writer = new StringWriter();
set.WriteXml(writer, XmlWriteMode.WriteSchema);
newSet.ReadXml(new StringReader(writer.ToString()), XmlReadMode.ReadSchema);
static DataSet RoundTripViaBinary(DataSet set)
return BinaryFormatterHelper.FromBinary<DataSet>(BinaryFormatterHelper.ToBinary(set));
public static string GetDataSetXsd()
var xsd = @"<?xml version=""1.0"" encoding=""utf-16""?>
<xs:schema id=""NewDataSet"" xmlns="""" xmlns:xs=""http://www.w3.org/2001/XMLSchema"" xmlns:msdata=""urn:schemas-microsoft-com:xml-msdata"">
<xs:element name=""NewDataSet"" msdata:IsDataSet=""true"" msdata:UseCurrentLocale=""true"">
<xs:choice minOccurs=""0"" maxOccurs=""unbounded"">
<xs:element name=""Table"">
<xs:element name=""ProjectID"" type=""xs:string"" minOccurs=""0"" />
<xs:element name=""Title"" type=""xs:string"" minOccurs=""0"" />
<xs:element name=""ProjectType"" type=""xs:string"" minOccurs=""0"" />
public static DataSet CreateDataSet()
DataSet dataSet = new DataSet();
using (var reader = new StringReader(GetDataSetXsd()))
dataSet.ReadXmlSchema(reader);
public static void PopulateDataSet(DataSet dataSet, int start, int count)
for (int i = start; i < start+count; i++)
var row = dataSet.Tables["Table"].NewRow();
row["ProjectID"] = (i * 2).ToString();
row["Title"] = "Project Number " + i.ToString();
row["ProjectType"] = ((ProjectTypes)(i % Enum.GetNames(typeof(ProjectTypes)).Length)).ToString();
dataSet.Tables["Table"].Rows.Add(row);
dataSet.Tables["Table"].Rows.Add(dataSet.Tables["Table"].NewRow());
public static class XmlSerializationHelper
public static T LoadFromXml<T>(this string xmlString, XmlSerializer serial = null)
serial = serial ?? new XmlSerializer(typeof(T));
using (var reader = new StringReader(xmlString))
return (T)serial.Deserialize(reader);
public static string GetXml<T>(this T obj, XmlSerializer serializer = null, bool omitStandardNamespaces = false)
XmlSerializerNamespaces ns = null;
if (omitStandardNamespaces)
ns = new XmlSerializerNamespaces();
using (var textWriter = new StringWriter())
var settings = new XmlWriterSettings() { Indent = true };
using (var xmlWriter = XmlWriter.Create(textWriter, settings))
(serializer ?? new XmlSerializer(obj.GetType())).Serialize(xmlWriter, obj, ns);
return textWriter.ToString();
public static partial class BinaryFormatterHelper
public static byte[] ToBinary<T>(T obj)
using (var stream = new MemoryStream())
new BinaryFormatter().Serialize(stream, obj);
public static T FromBinary<T>(byte[] data)
using (var stream = new MemoryStream(data))
var formatter = new BinaryFormatter();
var obj = formatter.Deserialize(stream);
public static void Main()
Console.WriteLine("Environment version: {0} ({1})", System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription , GetNetCoreVersion());
Console.WriteLine("Failed with unhandled exception: ");
public static string GetNetCoreVersion()
var assembly = typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly;
var assemblyPath = assembly.Location.Split(new[] { '/', '\\' }, StringSplitOptions.RemoveEmptyEntries);
int netCoreAppIndex = Array.IndexOf(assemblyPath, "Microsoft.NETCore.App");
if (netCoreAppIndex > 0 && netCoreAppIndex < assemblyPath.Length - 2)
return assemblyPath[netCoreAppIndex + 1];