简体   繁体   English

如何将XML文档映射到实体框架对象?

[英]How to map XML document to entity framework object?

I have following entity framework object: 我有以下实体框架对象:

namespace Proj.Accounting.Entity
{
    using System;
    using System.Collections.Generic;
    using System.Xml.Serialization;

    public partial class DocumentStatus
    {
        public DocumentStatus()
        {
            this.Documents = new HashSet<Document>();
            this.DocumentsTrackings = new HashSet<DocumentsTracking>();
            this.DocumentsTrackingChildDocuments = new HashSet<DocumentsTrackingChildDocument>();
        }
        [XmlElement("StateId")]
        public int StateId { get; set; }
        [XmlElement("StateName")]
        public string StateName { get; set; }
        [XmlElement("GroupId")]
        public Nullable<int> GroupId { get; set; }

        public virtual ICollection<Document> Documents { get; set; }
        public virtual ICollection<DocumentsTracking> DocumentsTrackings { get; set; }
        public virtual ICollection<DocumentsTrackingChildDocument> DocumentsTrackingChildDocuments { get; set; }
    }
}

I have following class to map the entity with the xml fields (doesn't work like that): 我有下面的类来映射具有xml字段的实体(不能那样工作):

using System;
using System.Collections;
using System.IO;
using System.Xml.Serialization;

namespace Proj.Accounting.Data
{
    class XMLObjects
    {
        public static T ConvertXmlToClass<T>(string xml)
        {
            var serializer = new XmlSerializer(typeof(T));
            return (T)serializer.Deserialize(new StringReader(xml));
        }
    }
}

and the method I am using to map the data: 以及我用来映射数据的方法:

private void button1_Click(object sender, EventArgs e)
{
    string xml = "";
    xml +=  "<?xml version=\"1.0\" encoding=\"UTF - 8\"?>";
    xml +=  "<root>";
    xml += " <success>true</success>";
    xml +=  " <data>";
    xml += " <item>";
    xml += " <StateId>0</StateId>";
    xml += " <StateName>Шаблон</StateName>";
    xml += " <GroupId>0</GroupId>";
    xml += " </item>";
    xml +=  "</root>";
    DocumentStatus documentStatus = new DocumentStatus();
    documentStatus = XMLObjects.ConvertXmlToClass<DocumentStatus>(xml);
    int a = 0;
}

I am getting following exception 我正在关注异常

System.InvalidOperationException was unhandled   HResult=-2146233079  
 Message=There was an error reflecting type 'Proj.Accounting.Entity.DocumentStatus'. Source=System.Xml  
 StackTrace:
        at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
        at System.Xml.Serialization.XmlReflectionImporter.ImportElement(TypeModel model, XmlRootAttribute root, String defaultNamespace, RecursionLimiter limiter)
        at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(Type type, XmlRootAttribute root, String defaultNamespace)
        at System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace)
        at System.Xml.Serialization.XmlSerializer..ctor(Type type)
        at Proj.Accounting.Data.XMLObjects.ConvertXmlToClass[T](String xml) in c:\Users\username\Dropbox\Dev\Proj.Accounting\Proj.Accounting.Data\XMLObjects.cs:line 12
        at Proj.Accounting.Data.MainForm.button1_Click(Object sender, EventArgs e) in c:\Users\username\Dropbox\Dev\Proj.Accounting\Proj.Accounting.Data\MainForm.cs:line 36
        at System.Windows.Forms.Control.OnClick(EventArgs e)
        at System.Windows.Forms.Button.OnClick(EventArgs e)
        at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
        at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
        at System.Windows.Forms.Control.WndProc(Message& m)
        at System.Windows.Forms.ButtonBase.WndProc(Message& m)
        at System.Windows.Forms.Button.WndProc(Message& m)
        at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message&m)
        at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
        at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
        at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
        at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
        at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
        at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
        at System.Windows.Forms.Application.Run(Form mainForm)
        at Proj.Accounting.Data.Program.Main() in c:\Users\username\Dropbox\Dev\Proj.Accounting\Proj.Accounting.Data\Program.cs:line 19
        at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
        at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
        at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
        at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
        at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
        at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
        at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
        at System.Threading.ThreadHelper.ThreadStart()   InnerException: System.InvalidOperationException HResult=-2146233079
        Message=Cannot serialize member 'Proj.Accounting.Entity.DocumentStatus.Documents' of type 'System.Collections.Generic.ICollection`1[[Proj.Accounting.Entity.Document,
 Proj.Accounting.Entity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]', see inner exception for more details.
        Source=System.Xml
        StackTrace:
             at System.Xml.Serialization.StructModel.CheckSupportedMember(TypeDesc typeDesc, MemberInfo member, Type type)
             at System.Xml.Serialization.StructModel.GetPropertyModel(PropertyInfo propertyInfo)
             at System.Xml.Serialization.StructModel.GetFieldModel(MemberInfo memberInfo)
             at System.Xml.Serialization.XmlReflectionImporter.InitializeStructMembers(StructMapping mapping, StructModel model, Boolean openModel, String typeName, RecursionLimiter limiter)
             at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(StructModel model, String ns, Boolean openModel, XmlAttributes a, RecursionLimiter limiter)
             at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(TypeModel model, String ns, ImportContext context, String dataType, XmlAttributes a, Boolean repeats, Boolean openModel, RecursionLimiter limiter)
        InnerException: System.NotSupportedException
             HResult=-2146233067
             Message=Cannot serialize member Proj.Accounting.Entity.DocumentStatus.Documents of type
 System.Collections.Generic.ICollection`1[[Proj.Accounting.Entity.Document,
 Proj.Accounting.Entity, Version=1.0.0.0, Culture=neutral,
 PublicKeyToken=null]] because it is an interface.
             InnerException:

Everything is said in : 一切都说在:

Cannot serialize member Proj.Accounting.Entity.DocumentStatus.Documents of type 无法序列化类型为Proj.Accounting.Entity.DocumentStatus.Documents成员
System.Collections.Generic.ICollection1[[Proj.Accounting.Entity.Document, Proj.Accounting.Entity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] because it is an interface System.Collections.Generic.ICollection1 [[Proj.Accounting.Entity.Document,Proj.Accounting.Entity,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]], 因为它是接口

Interface are not serializable. 接口不可序列化。 Transform all your ICollection properties to type HashSet to enable serialization of these items. 将所有ICollection属性转换为HashSet类型,以启用这些项目的序列化。

Serializable 可序列化

I think the problem is that your class Document is not serializable. 我认为问题在于您的班级Document无法序列化。 When you serialize an Object, all of their fields must be Serializable too. 序列化对象时,它们的所有字段也必须可序列化。 If you don't want to serialize the Documents member, mark it with [System.Xml.Serialization.XmlIgnoreAttribute] 如果您不想序列化Documents成员,请用[System.Xml.Serialization.XmlIgnoreAttribute]进行标记。

To serialize an Object to XML, use the method Serialize and to deserialize use the method Deserialize. 要将对象序列化为XML,请使用序列化方法,并反序列化请使用反序列化方法。 You don't need more than that. 您只需要这些。

More information: https://msdn.microsoft.com/es-es/library/system.xml.serialization.xmlserializer(v=vs.110).aspx 详细信息: https : //msdn.microsoft.com/es-es/library/system.xml.serialization.xmlserializer(v=vs.110).aspx


Tips 提示

Also, change your string concatenation to use StringBuilder. 另外,将您的字符串连接更改为使用StringBuilder。 If this is test code, remember that you can use += operator on strings, which results on Clean Code. 如果这是测试代码,请记住您可以在字符串上使用+ =运算符,这将在“清洁代码”中产生。

Examples: 例子:

string xml = "";
xml = xml + "<?xml version=\"1.0\" encoding=\"UTF - 8\"?>";
xml = xml + "<root>";

Using += operator (Same result but cleaner) 使用+ =运算符(结果相同但更干净)

string xml = "";
xml += "<?xml version=\"1.0\" encoding=\"UTF - 8\"?>";
xml += "<root>";

Using StringBuilder (Best and fastest way) 使用StringBuilder(最佳和最快的方法)

StringBuilder xml = new StringBuilder();
xml.Append("<?xml version=\"1.0\" encoding=\"UTF - 8\"?>");
xml.Append("<root>");

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM