如何将类型实体的observablecollection序列化为xml(How to serialize an observablecollection of type entity to xml)

我正在使用Entity Framework在WPF应用程序上使用VS 2015。 在这个应用程序中,我在我的一个WPF窗口中可以序列化一个画布,我在其上获得了一些自定义控件。

今天我尝试向我的一个自定义控件添加一个新的dependencyproperty,它是一个observablecollection,类型是一个实体(在我的例子中是一个名为Formulas的表)。

通常,不可能序列化泛型类型。

所以我在我的应用程序中添加了一个新类,并在我的代码中将其用作属性类型。

public class AssignedFormulasCollection : ObservableCollection<Formulas> { public AssignedFormulasCollection() { } public AssignedFormulasCollection(List<Formulas> list) : base(list) { } }

这是实体Formulas的代码:

public partial class Formulas { public Formulas() { this.Formula_Attributes = new HashSet<Formula_Attributes>(); this.Formula_Field_Attributes = new HashSet<Formula_Field_Attributes>(); this.Input_Field_Formulas = new HashSet<Input_Field_Formulas>(); this.Stepfunctions = new HashSet<Stepfunctions>(); } public int formula_id { get; set; } public int description_id { get; set; } public string formula_name { get; set; } public string formula_version { get; set; } public string formula_expression { get; set; } public string formula_type { get; set; } public Nullable<float> result1 { get; set; } public Nullable<float> result2 { get; set; } public Nullable<float> result3 { get; set; } public Nullable<int> version { get; set; } public string changer { get; set; } public Nullable<System.DateTime> change_date { get; set; } public virtual Descriptions Descriptions { get; set; } public virtual ICollection<Formula_Attributes> Formula_Attributes { get; set; } public virtual ICollection<Formula_Field_Attributes> Formula_Field_Attributes { get; set; } public virtual ICollection<Input_Field_Formulas> Input_Field_Formulas { get; set; } public virtual ICollection<Stepfunctions> Stepfunctions { get; set; } }

我通过这种方法序列化画布:

public string SerializeControlToXaml(FrameworkElement element) { var elementToXaml = new StringBuilder(); var settings = new XmlWriterSettings(); settings.Indent = true; settings.OmitXmlDeclaration = true; var serializationManager = new XamlDesignerSerializationManager(XmlWriter.Create(elementToXaml, settings)); serializationManager.XamlWriterMode = XamlWriterMode.Expression; XamlWriter.Save(element, serializationManager); var xaml = elementToXaml.ToString(); return xaml; }

但是当我尝试使用自定义控件序列化画布时,我收到以下错误消息:

用户代码未处理System.Reflection.TargetInvocationException。 HResult = -2146232828 Message = System.Data.Entity.DynamicProxies.Formulas_CF5776A4E794BA378BEBDBE1E29E7967B4AACCF844AB5416006C852677145A0A对象的PropertyAccessorDescriptions导致以下异常:ObjectContext实例已被丢弃,无法再用于需要连接的事务。

来源=系统

堆栈跟踪: 在System.ComponentModel.ReflectPropertyDescriptor.GetValue(对象组件) 在System.Windows.Markup.Primitives.ElementProperty.get_Value() 在System.Windows.Markup.Primitives.ElementPropertyBase.get_IsComposite() 在System.Windows.Markup.Primitives.MarkupWriter.RecordNamespaces(ScopeScope,MarkupObject项,IValueSerializerContext上下文,布尔lastWasString) 在System.Windows.Markup.Primitives.MarkupWriter.RecordNamespaces(ScopeScope,MarkupObject项,IValueSerializerContext上下文,布尔lastWasString)在System.Windows.Markup.Primitives.MarkupWriter.RecordNamespaces(ScopeScope,MarkupObject项,IValueSerializerContext上下文,布尔lastWasString)在系统.Windows.Markup.Primitives.MarkupWriter.RecordNamespaces(ScopeScope,MarkupObject项,IValueSerializerContext上下文,Boolean lastWasString)在System.Windows.Markup.Primitives.MarkupWriter.WriteItem(MarkupObject项)At System.Windows.Markup.Primitives.MarkupWriter.SaveAsXml (XmlWriter writer,MarkupObject项)在System.Windows.Markup.Primitives.MarkupWriter.SaveAsXml(XmlWriter writer,Object instance,XamlDesignerSerializationManager manager)At System.Windows.Markup.XamlWriter.Save(Object obj,XamlDesignerSerializationManager manager)At P16Common.XamlDeSerializer .SerializeControlToXaml(FrameworkElement元素) 在C:\ svn_checkout \ P16_RoeV \ Sourcen \ P16Admintool_develop \ P16Common \ XamlDeSerializer.cs:第50行。在P16Common.CommonMethods.SerializeToXml(FrameworkElement designerGrid)到C:\ svn_checkout \ P16_RoeV \ Sourcen \ P16Admintool_develop \ P16Common \ CommonMethods.cs:Line 61.在P16Admintool.Helper.InputMaskHelper.UpdateInputMask(InputMasksView designerwindow)到C:\ svn_checkout \ P16_RoeV \ Resources \ P16Admintool_develop \ P16Admintool \ Helper \ InputMaskHelper.cs:第39行。在C16中的P16Admintool.ViewModels.ChangeElementPropertiesViewModel.SetElementProperties(): \ svn_checkout \ P16_RoeV \ Sourcen \ P16Admintool_develop \ P16Admintool \ ViewModels \ ChangeElementPropertiesViewModel.cs:第152行。对于C:\ svn_checkout \ P16_RoeV \ Resources \ P16Admintool_develop \ P16Admintool \ Views中的P16Admintool.Views.ChangeElementProperties.btn_set_properties_Click(Object sender,RoutedEventArgs e) \ ChangeElementProperties.xaml.cs:第77行。 在System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target,RoutedEventArgs routedEventArgs)在System.Windows.EventRoute.InvokeHandlersImpl(Object source,RoutedEventArgsArgs,Boolean reRaised)At System.Windows.UIElement.RaiseEventImpl(DependencyObject sender,RoutedEventArgs args)At System。 Windows.UIElement.RaiseEvent(RoutedEventArgs e)在System.Windows.Controls.Primitives.ButtonBase.OnClick()At System.Windows.Controls.Button.OnClick()At System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp(MouseButtonEventArgs e )在System.Windows.UIElement.OnMouseLeftButtonUpThunk(Object sender,MouseButtonEventArgs e)System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler,Object genericTarget)At System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler,Object target)At System .Windows.RoutedEventHandlerInfo.InvokeHandler(Object target,RoutedEventArgs routedEventArgs)在System.Windows.EventRoute.InvokeHandlersImpl(Object source,RoutedEventArgsArgs,Boolean reRaised)At System.Windows.UIElement.ReRaiseEventAs(DependencyObject sender,RoutedEventArgs args,RoutedEvent newEvent)At System.Windows.UIElement.OnMouseUpThunk(Object sender,MouseButtonEventArgs) e)在System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler(Delegate genericHandler,Object genericTarget)At System.Windows.RoutedEventArgs.InvokeHandler(Delegate handler,Object target)At System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target,RoutedEventArgs routedEventArgs)At System.Windows.EventRoute.InvokeHandlersImpl(Object source,RoutedEventArgsArgs,Boolean reRaised)在System.Windows.UIElement.RaiseEventImpl(DependencyObject sender,RoutedEventArgs args)在System.Windows.UIElement.RaiseTrustedEvent(RoutedEventArgs args)处于System.Windows.UIElement。 RaiseEvent(RoutedEventAr gs args,布尔值信任)在System.Windows.Input.InputManager.ProcessStagingArea()处于System.Windows.Input.InputManager.ProcessInput(InputEventArgs输入)

I'm working with VS 2015 on a WPF application using Entity Framework. In this application I have in one of my WPF window the possibility to serialize a canvas on which I got some custom controls.

Today I tried to add to one of my custom controls a new dependencyproperty which is an observablecollection which type is an entity (in my case a table called Formulas).

Normally it's not possible to serialize generic types.

So I added a new class to my app and used that in my code as property type.

public class AssignedFormulasCollection : ObservableCollection<Formulas> { public AssignedFormulasCollection() { } public AssignedFormulasCollection(List<Formulas> list) : base(list) { } }

This is the code of the entity Formulas:

public partial class Formulas { public Formulas() { this.Formula_Attributes = new HashSet<Formula_Attributes>(); this.Formula_Field_Attributes = new HashSet<Formula_Field_Attributes>(); this.Input_Field_Formulas = new HashSet<Input_Field_Formulas>(); this.Stepfunctions = new HashSet<Stepfunctions>(); } public int formula_id { get; set; } public int description_id { get; set; } public string formula_name { get; set; } public string formula_version { get; set; } public string formula_expression { get; set; } public string formula_type { get; set; } public Nullable<float> result1 { get; set; } public Nullable<float> result2 { get; set; } public Nullable<float> result3 { get; set; } public Nullable<int> version { get; set; } public string changer { get; set; } public Nullable<System.DateTime> change_date { get; set; } public virtual Descriptions Descriptions { get; set; } public virtual ICollection<Formula_Attributes> Formula_Attributes { get; set; } public virtual ICollection<Formula_Field_Attributes> Formula_Field_Attributes { get; set; } public virtual ICollection<Input_Field_Formulas> Input_Field_Formulas { get; set; } public virtual ICollection<Stepfunctions> Stepfunctions { get; set; } }

I serialize the canvas by this method:

public string SerializeControlToXaml(FrameworkElement element) { var elementToXaml = new StringBuilder(); var settings = new XmlWriterSettings(); settings.Indent = true; settings.OmitXmlDeclaration = true; var serializationManager = new XamlDesignerSerializationManager(XmlWriter.Create(elementToXaml, settings)); serializationManager.XamlWriterMode = XamlWriterMode.Expression; XamlWriter.Save(element, serializationManager); var xaml = elementToXaml.ToString(); return xaml; }

But when I try to serialize the canvas with the custom controls I get the following error message:

System.Reflection.TargetInvocationException was not handled by user code. HResult = -2146232828 Message = The PropertyAccessorDescriptions for the System.Data.Entity.DynamicProxies.Formulas_CF5776A4E794BA378BEBDBE1E29E7967B4AACCF844AB5416006C852677145A0A object caused the following exception: The ObjectContext instance was discarded and can no longer be used for transactions that require a connection.

Source = System

StackTrace: At System.ComponentModel.ReflectPropertyDescriptor.GetValue (Object component) At System.Windows.Markup.Primitives.ElementProperty.get_Value () At System.Windows.Markup.Primitives.ElementPropertyBase.get_IsComposite () At System.Windows.Markup.Primitives.MarkupWriter.RecordNamespaces (ScopeScope, MarkupObject item, IValueSerializerContext context, Boolean lastWasString)        At System.Windows.Markup.Primitives.MarkupWriter.RecordNamespaces (ScopeScope, MarkupObject item, IValueSerializerContext context, Boolean lastWasString)        At System.Windows.Markup.Primitives.MarkupWriter.RecordNamespaces (ScopeScope, MarkupObject item, IValueSerializerContext context, Boolean lastWasString)        At System.Windows.Markup.Primitives.MarkupWriter.RecordNamespaces (ScopeScope, MarkupObject item, IValueSerializerContext context, Boolean lastWasString)        At System.Windows.Markup.Primitives.MarkupWriter.WriteItem (MarkupObject item)        At System.Windows.Markup.Primitives.MarkupWriter.SaveAsXml (XmlWriter writer, MarkupObject item)        At System.Windows.Markup.Primitives.MarkupWriter.SaveAsXml (XmlWriter writer, Object instance, XamlDesignerSerializationManager manager)        At System.Windows.Markup.XamlWriter.Save (Object obj, XamlDesignerSerializationManager manager)        At P16Common.XamlDeSerializer.SerializeControlToXaml (FrameworkElement element) in C: \ svn_checkout \ P16_RoeV \ Sourcen \ P16Admintool_develop \ P16Common \ XamlDeSerializer.cs: Line 50.        At P16Common.CommonMethods.SerializeToXml (FrameworkElement designerGrid) to C: \ svn_checkout \ P16_RoeV \ Sourcen \ P16Admintool_develop \ P16Common \ CommonMethods.cs: Line 61.        At P16Admintool.Helper.InputMaskHelper.UpdateInputMask (InputMasksView designerwindow) to C: \ svn_checkout \ P16_RoeV \ Resources \ P16Admintool_develop \ P16Admintool \ Helper \ InputMaskHelper.cs: Line 39.        At P16Admintool.ViewModels.ChangeElementPropertiesViewModel.SetElementProperties () in C: \ svn_checkout \ P16_RoeV \ Sourcen \ P16Admintool_develop \ P16Admintool \ ViewModels \ ChangeElementPropertiesViewModel.cs: Line 152.        For P16Admintool.Views.ChangeElementProperties.btn_set_properties_Click (Object sender, RoutedEventArgs e) in C: \ svn_checkout \ P16_RoeV \ Resources \ P16Admintool_develop \ P16Admintool \ Views \ ChangeElementProperties.xaml.cs: Line 77.        At System.Windows.RoutedEventHandlerInfo.InvokeHandler (Object target, RoutedEventArgs routedEventArgs)        At System.Windows.EventRoute.InvokeHandlersImpl (Object source, RoutedEventArgsArgs, Boolean reRaised)        At System.Windows.UIElement.RaiseEventImpl (DependencyObject sender, RoutedEventArgs args)        At System.Windows.UIElement.RaiseEvent (RoutedEventArgs e)        At System.Windows.Controls.Primitives.ButtonBase.OnClick ()        At System.Windows.Controls.Button.OnClick ()        At System.Windows.Controls.Primitives.ButtonBase.OnMouseLeftButtonUp (MouseButtonEventArgs e)        At System.Windows.UIElement.OnMouseLeftButtonUpThunk (Object sender, MouseButtonEventArgs e)        At System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler (Delegate genericHandler, Object genericTarget)        At System.Windows.RoutedEventArgs.InvokeHandler (Delegate handler, Object target)        At System.Windows.RoutedEventHandlerInfo.InvokeHandler (Object target, RoutedEventArgs routedEventArgs)        At System.Windows.EventRoute.InvokeHandlersImpl (Object source, RoutedEventArgsArgs, Boolean reRaised)        At System.Windows.UIElement.ReRaiseEventAs (DependencyObject sender, RoutedEventArgs args, RoutedEvent newEvent)        At System.Windows.UIElement.OnMouseUpThunk (Object sender, MouseButtonEventArgs e)        At System.Windows.Input.MouseButtonEventArgs.InvokeEventHandler (Delegate genericHandler, Object genericTarget)        At System.Windows.RoutedEventArgs.InvokeHandler (Delegate handler, Object target)        At System.Windows.RoutedEventHandlerInfo.InvokeHandler (Object target, RoutedEventArgs routedEventArgs)        At System.Windows.EventRoute.InvokeHandlersImpl (Object source, RoutedEventArgsArgs, Boolean reRaised)        At System.Windows.UIElement.RaiseEventImpl (DependencyObject sender, RoutedEventArgs args)        At System.Windows.UIElement.RaiseTrustedEvent (RoutedEventArgs args)        At System.Windows.UIElement.RaiseEvent (RoutedEventArgs args, Boolean trusted)        At System.Windows.Input.InputManager.ProcessStagingArea ()        At System.Windows.Input.InputManager.ProcessInput (InputEventArgs input)

最满意答案

延迟加载和序列化不能很好地混合,请参阅以下有关https://msdn.microsoft.com/en-us/library/jj574232(v=vs.113).aspx的文章。

在您的情况下,您可能需要急切地加载所有依赖项,即以下属性的集合。 就像你说的那样,首先从Descriptions属性开始可能是一个好主意。

public virtual Descriptions Descriptions { get; set; } public virtual ICollection<Formula_Attributes> Formula_Attributes { get; set; } public virtual ICollection<Formula_Field_Attributes> Formula_Field_Attributes { get; set; } public virtual ICollection<Input_Field_Formulas> Input_Field_Formulas { get; set; } public virtual ICollection<Stepfunctions> Stepfunctions { get; set; }

每当您调用上下文加载Formulas您将需要在Descriptions和任何其他延迟加载的集合上调用.Include(..) 。

Lazy loading and serialization do not mix well, see the following article on why https://msdn.microsoft.com/en-us/library/jj574232(v=vs.113).aspx.

In your case you might need to eagerly load all the dependencies i.e. collections of the following properties. And like you said, it might be a good idea to start with the Descriptions property first.

public virtual Descriptions Descriptions { get; set; } public virtual ICollection<Formula_Attributes> Formula_Attributes { get; set; } public virtual ICollection<Formula_Field_Attributes> Formula_Field_Attributes { get; set; } public virtual ICollection<Input_Field_Formulas> Input_Field_Formulas { get; set; } public virtual ICollection<Stepfunctions> Stepfunctions { get; set; }

Whenever you call your context to load Formulas you will need to call .Include(..) on the Descriptions and any other lazy loaded collections.

更多推荐