Entity framework 如何序列化ICollection类型的属性<;T>;在使用实体框架时

Entity framework 如何序列化ICollection类型的属性<;T>;在使用实体框架时,entity-framework,serialization,deserialization,Entity Framework,Serialization,Deserialization,我有一个如下所示的类 public class Survey { public Survey() { SurveyResponses=new List<SurveyResponse>(); } [Key] public Guid SurveyId { get; set; } public string SurveyName { get; set; }

我有一个如下所示的类

public class Survey
    {
        public Survey()
        {
            SurveyResponses=new List<SurveyResponse>();
        }

        [Key]
        public Guid SurveyId { get; set; }
        public string SurveyName { get; set; }
        public string SurveyDescription { get; set; }
        public virtual ICollection<Question> Questions { get; set; }
        public virtual ICollection<SurveyResponse> SurveyResponses { get; set; }
    }
公共类调查
{
公众调查()
{
SurveyResponses=新列表();
}
[关键]
公共Guid SurveyId{get;set;}
公共字符串SurveyName{get;set;}
公共字符串SurveyDescription{get;set;}
公共虚拟ICollection问题{get;set;}
公共虚拟ICollection SurveyResponses{get;set;}
}
上面的代码给出了以下异常

无法序列化类型为的成员“SurveyGenerator.Survey.Questions” 'System.Collections.Generic.ICollection

当我将ICollection转换为List时,它会正确序列化


由于它是实体框架的POCO,我无法从类的外观将ICollection转换为List。ICollection属性正在定义外键关系?如果是这样,你就不想公开这些收藏了

例如:如果您遵循开发实体框架模型的最佳实践指南,那么您将有一个名为“问题”的单独类,该类将您的两个类连接在一起,如下所示:

public class Question
{
    [Key]
    public int Id { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }

    public virtual Survey Survey { get; set; }
}
如果是这样的话,你很可能会绕着圈子问问题->调查->收集->问题

我在使用EF、MVC3实现REST服务时遇到了类似的问题,无法序列化ICollection对象,然后意识到我不需要序列化,因为我无论如何都会单独调用该对象

出于您的目的更新的类如下所示:

public class Survey
{
    public Survey()
    {
        SurveyResponses=new List<SurveyResponse>();
    }

    [Key]
    public Guid SurveyId { get; set; }
    public string SurveyName { get; set; }
    public string SurveyDescription { get; set; }

    [XmlIgnore]
    [IgnoreDataMember]
    public virtual ICollection<Question> Questions { get; set; }

    [XmlIgnore]
    [IgnoreDataMember]
    public virtual ICollection<SurveyResponse> SurveyResponses { get; set; }
}
公共类调查
{
公众调查()
{
SurveyResponses=新列表();
}
[关键]
公共Guid SurveyId{get;set;}
公共字符串SurveyName{get;set;}
公共字符串SurveyDescription{get;set;}
[XmlIgnore]
[IgnoreDataMember]
公共虚拟ICollection问题{get;set;}
[XmlIgnore]
[IgnoreDataMember]
公共虚拟ICollection SurveyResponses{get;set;}
}

我希望这对您有所帮助。

ICollection更改为列表

公共类调查
{
公众调查()
{
SurveyResponses=新列表();
}
[关键]
公共Guid SurveyId{get;set;}
公共字符串SurveyName{get;set;}
公共字符串SurveyDescription{get;set;}
公共虚拟列表问题{get;set;}
公共虚拟列表调查响应{get;set;}
}

如果您不介意添加对assembly System.Runtime.Serialization的引用,您可以使用此代码,它将使用ICollection序列化对象,而无需更改对象的实现。下面的代码正在输出到字符串。您可以随意使用该流

    private string ConvertClassToXMLString<T>(T classObject)
    {
        using (var stream = new MemoryStream())
        {
            var serializer = new DataContractSerializer(classObject.GetType());
            serializer.WriteObject(stream, classObject);

            return Encoding.UTF8.GetString(stream.ToArray());
        }
    }
private string ConvertClassToXMLString(T类对象)
{
使用(var stream=new MemoryStream())
{
var serializer=新的DataContractSerializer(classObject.GetType());
serializer.WriteObject(流,类对象);
返回Encoding.UTF8.GetString(stream.ToArray());
}
}

我使用了Matthew Merryfull解决方案,效果很好

由于每次更新模型时我都使用EF designer生成实体,因此我会放弃手动更改。我必须更改用于生成模型的*.tt。我编辑了几行:

   public string NavigationProperty(NavigationProperty navigationProperty)
{
var enbleWebService = string.Empty;
if(navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ){
enbleWebService = string.Format("[XmlIgnore]{0}[IgnoreDataMember]{0}", Environment.NewLine);
}
    var endType = _typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType());
    return string.Format(
        CultureInfo.InvariantCulture,
        "{5} {0} {1} {2} {{ {3}get; {4}set; }}",
        AccessibilityAndVirtual(Accessibility.ForProperty(navigationProperty)),
        navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType,
        _code.Escape(navigationProperty),
        _code.SpaceAfter(Accessibility.ForGetter(navigationProperty)),
        _code.SpaceAfter(Accessibility.ForSetter(navigationProperty)),
         _code.Escape(enbleWebService));
}

 public string NavigationProperty(NavigationProperty navigationProperty)
{
var enbleWebService = string.Empty;
if(navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ){
    enbleWebService = string.Format("[XmlIgnore]{0}[IgnoreDataMember]{0}", Environment.NewLine);
}
    var endType = _typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType());
    return string.Format(
        CultureInfo.InvariantCulture,
        "{5} {0} {1} {2} {{ {3}get; {4}set; }}",
        AccessibilityAndVirtual(Accessibility.ForProperty(navigationProperty)),
        navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType,
        _code.Escape(navigationProperty),
        _code.SpaceAfter(Accessibility.ForGetter(navigationProperty)),
        _code.SpaceAfter(Accessibility.ForSetter(navigationProperty)),
         _code.Escape(enbleWebService));
}
公共字符串NavigationProperty(NavigationProperty NavigationProperty)
{
var enbleWebService=string.Empty;
if(navigationProperty.ToEndMember.RelationshipMultiplicity==RelationshipMultiplicity.Many){
enbleWebService=string.Format(“[XmlIgnore]{0}[IgnoreDataMember]{0}”,Environment.NewLine);
}
var endType=_typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType());
返回字符串格式(
CultureInfo.InvariantCulture,
“{5}{0}{1}{2}{{3}get;{4}set;}}”,
AccessibilityAndVirtual(Accessibility.ForProperty(navigationProperty)),
navigationProperty.ToEndMember.RelationshipMultiplicity==RelationshipMultiplicity.Many?(“ICollection”):endType,
_代码.转义(navigationProperty),
_code.SpaceAfter(Accessibility.遗忘器(navigationProperty)),
_code.SpaceAfter(Accessibility.ForSetter(navigationProperty)),
_逃生代码(enbleWebService));
}
公共字符串NavigationProperty(NavigationProperty NavigationProperty)
{
var enbleWebService=string.Empty;
if(navigationProperty.ToEndMember.RelationshipMultiplicity==RelationshipMultiplicity.Many){
enbleWebService=string.Format(“[XmlIgnore]{0}[IgnoreDataMember]{0}”,Environment.NewLine);
}
var endType=_typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType());
返回字符串格式(
CultureInfo.InvariantCulture,
“{5}{0}{1}{2}{{3}get;{4}set;}}”,
AccessibilityAndVirtual(Accessibility.ForProperty(navigationProperty)),
navigationProperty.ToEndMember.RelationshipMultiplicity==RelationshipMultiplicity.Many?(“ICollection”):endType,
_代码.转义(navigationProperty),
_code.SpaceAfter(Accessibility.遗忘器(navigationProperty)),
_code.SpaceAfter(Accessibility.ForSetter(navigationProperty)),
_逃生代码(enbleWebService));
}

还要检查本文,以防在序列化方面遇到问题。对我来说,问题是没有默认构造函数。例子:
列出MyVar;//MyClass需要一个公共构造函数

检查这个答案是否能帮助您,如果您先使用List而不是带有EF代码的ICollection,会发生什么?我的印象是它仍然有效。这篇文章让我觉得结合这个答案需要一个默认构造函数。公共MyClass();
   public string NavigationProperty(NavigationProperty navigationProperty)
{
var enbleWebService = string.Empty;
if(navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ){
enbleWebService = string.Format("[XmlIgnore]{0}[IgnoreDataMember]{0}", Environment.NewLine);
}
    var endType = _typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType());
    return string.Format(
        CultureInfo.InvariantCulture,
        "{5} {0} {1} {2} {{ {3}get; {4}set; }}",
        AccessibilityAndVirtual(Accessibility.ForProperty(navigationProperty)),
        navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType,
        _code.Escape(navigationProperty),
        _code.SpaceAfter(Accessibility.ForGetter(navigationProperty)),
        _code.SpaceAfter(Accessibility.ForSetter(navigationProperty)),
         _code.Escape(enbleWebService));
}

 public string NavigationProperty(NavigationProperty navigationProperty)
{
var enbleWebService = string.Empty;
if(navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ){
    enbleWebService = string.Format("[XmlIgnore]{0}[IgnoreDataMember]{0}", Environment.NewLine);
}
    var endType = _typeMapper.GetTypeName(navigationProperty.ToEndMember.GetEntityType());
    return string.Format(
        CultureInfo.InvariantCulture,
        "{5} {0} {1} {2} {{ {3}get; {4}set; }}",
        AccessibilityAndVirtual(Accessibility.ForProperty(navigationProperty)),
        navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many ? ("ICollection<" + endType + ">") : endType,
        _code.Escape(navigationProperty),
        _code.SpaceAfter(Accessibility.ForGetter(navigationProperty)),
        _code.SpaceAfter(Accessibility.ForSetter(navigationProperty)),
         _code.Escape(enbleWebService));
}