C# 将DataContract作为XML持久化到数据库中

C# 将DataContract作为XML持久化到数据库中,c#,xml,wcf,datacontract,C#,Xml,Wcf,Datacontract,我正在为WCF服务开发一种“存储转发”应用程序。我想将消息保存在数据库中,作为原始XML blob,即XElement。我在将datacontract转换为数据库调用所需的XElement类型时遇到了一些问题。有什么想法吗?我不确定将其放入XElement的最有效方法,但要将其放入字符串,只需运行: DataContractSerializer serializer = new DataContractSerializer(typeof(Foo)); using (MemoryStream me

我正在为WCF服务开发一种“存储转发”应用程序。我想将消息保存在数据库中,作为原始XML blob,即XElement。我在将datacontract转换为数据库调用所需的XElement类型时遇到了一些问题。有什么想法吗?

我不确定将其放入XElement的最有效方法,但要将其放入字符串,只需运行:

DataContractSerializer serializer = new DataContractSerializer(typeof(Foo));
using (MemoryStream memStream = new MemoryStream())
{
    serializer.WriteObject(memStream, fooInstance);
    byte[] blob = memStream.ToArray();
}

这将以字符串的形式返回,您可以将其放入数据库的xml列中。下面是一个很好的通用方法,可以用来序列化数据契约

public static string Serialize<T>(T obj)
{
    StringBuilder sb = new StringBuilder();
    DataContractSerializer ser = new DataContractSerializer(typeof(T));
    ser.WriteObject(XmlWriter.Create(sb), obj);
    return sb.ToString();
}
公共静态字符串序列化(T obj)
{
StringBuilder sb=新的StringBuilder();
DataContractSerializer ser=新的DataContractSerializer(typeof(T));
ser.WriteObject(XmlWriter.Create(sb),obj);
使某人返回字符串();
}

顺便说一句,您是否正在使用LINQtoSQL?我问这个问题的原因是因为你问题的关键部分。如果是这种情况,您可以在.dbml设计器中对此进行修改,以使用字符串作为CLR类型,而不是默认的XElement。

如果您的数据库是SQL Server 2005或更高版本,则可以使用XML数据类型:

private readonly DataContractToSerialize _testContract =
    new DataContractToSerialize
        {
            ID = 1,
            Name = "One",
            Children =
                {
                    new ChildClassToSerialize {ChildMember = "ChildOne"},
                    new ChildClassToSerialize {ChildMember = "ChildTwo"}
                }
        };

public void SerializeDataContract()
{
    using (var outputStream = new MemoryStream())
    {
        using (var writer = XmlWriter.Create(outputStream))
        {
            var serializer =
                new DataContractSerializer(_testContract.GetType());
            if (writer != null)
            {
                serializer.WriteObject(writer, _testContract);
            }
        }

        outputStream.Position = 0;
        using (
            var conn =
                new SqlConnection(Settings.Default.ConnectionString))
        {
            conn.Open();

            const string INSERT_COMMAND =
                @"INSERT INTO XmlStore (Data) VALUES (@Data)";
            using (var cmd = new SqlCommand(INSERT_COMMAND, conn))
            {
                using (var reader = XmlReader.Create(outputStream))
                {
                    var xml = new SqlXml(reader);

                    cmd.Parameters.Clear();
                    cmd.Parameters.AddWithValue("@Data", xml);
                    cmd.ExecuteNonQuery();
                }
            }
        }
    }
}

我尝试使用Jason w'Serialize函数,该函数使用StringBuilder,但它为LingToSQL设计器生成的表类返回空字符串 具有[DataContract()]属性

但是如果我按照AgileJon的建议序列化到字节数组

然后使用UTF7编码转换为字符串,它创建可读的XML字符串

 static string DataContractSerializeUsingByteArray<T>(T obj)
    {
        string sRet = "";
        DataContractSerializer serializer = new DataContractSerializer(typeof(T)); 
        using (MemoryStream memStream = new MemoryStream()) 
        {
            serializer.WriteObject(memStream, obj); 
            byte[] blob = memStream.ToArray(); 
            var encoding= new System.Text.UTF7Encoding();
            sRet = encoding.GetString(blob);
        }
        return sRet;
    } 
静态字符串DataContractSerializeUsingByteArray(T obj)
{
字符串sRet=“”;
DataContractSerializer serializer=新的DataContractSerializer(typeof(T));
使用(MemoryStream memStream=new MemoryStream())
{
serializer.WriteObject(memStream,obj);
字节[]blob=memStream.ToArray();
var encoding=new System.Text.UTF7Encoding();
sRet=encoding.GetString(blob);
}
返回sRet;
} 
不知道为什么stringBuilder解决方案不起作用。

投票最多的答案(Jason W.posted)对我不起作用。我不知道为什么这个答案获得了最多的选票。但在四处搜索后,我发现了这个

为我的项目工作。我只是有几个类,将datacontract和datamemeber属性放在类和属性上,然后想要得到一个XML字符串,我可以将其写入数据库

上面链接的代码,以防变成404:

序列化:

var serializer = new DataContractSerializer(tempData.GetType());
using (var backing = new System.IO.StringWriter())
using (var writer = new System.Xml.XmlTextWriter(backing))
{
    serializer.WriteObject(writer, tempData);
    data.XmlData = backing.ToString();
}
var serializer = new DataContractSerializer(typeof(T));
using (var backing = new System.IO.StringReader(data.XmlData))
using (var reader = new System.Xml.XmlTextReader(backing))
{
    return serializer.ReadObject(reader) as T;
}
反序列化:

var serializer = new DataContractSerializer(tempData.GetType());
using (var backing = new System.IO.StringWriter())
using (var writer = new System.Xml.XmlTextWriter(backing))
{
    serializer.WriteObject(writer, tempData);
    data.XmlData = backing.ToString();
}
var serializer = new DataContractSerializer(typeof(T));
using (var backing = new System.IO.StringReader(data.XmlData))
using (var reader = new System.Xml.XmlTextReader(backing))
{
    return serializer.ReadObject(reader) as T;
}
XElement与“原始xml blob”不同。前者是一种类型,便于使用XML进行此操作。另一个是具有特定格式的字符串。您可以将[DataContract]修饰的任何类型保存为XML字符串。(示例见下文)。XElement-你可以把它放在你的credenza上,你不需要它。