简体   繁体   中英

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):

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
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

Interface are not serializable. Transform all your ICollection properties to type HashSet to enable serialization of these items.

Serializable

I think the problem is that your class Document is not serializable. 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]

To serialize an Object to XML, use the method Serialize and to deserialize use the method Deserialize. You don't need more than that.

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


Tips

Also, change your string concatenation to use 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 xml = new StringBuilder();
xml.Append("<?xml version=\"1.0\" encoding=\"UTF - 8\"?>");
xml.Append("<root>");

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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