如何序列化 ICollection 类型的属性使用实体框架时

发布于 2024-12-05 22:10:15 字数 742 浏览 0 评论 0 原文

我有一个类,如下所示

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

上面的代码给出了以下异常

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

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

,因为它是实体框架的 POCO,所以我无法将 ICollection 转换为 List

I have a class as shown below

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

The above code gives me following exception

Cannot serialize member 'SurveyGenerator.Survey.Questions' of type
'System.Collections.Generic.ICollection

When i convert the ICollection to List it serializes properly

Since it is POCO of Entity Framework, i cannot convert ICollection to List

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

赠佳期 2024-12-12 22:10:15

从类的外观来看,ICollection 属性正在定义外键关系?如果是这样,您就不想公开展示这些藏品。

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

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

如果是这种情况,您很可能会绕圈调用问题 ->调查-> ICollection->问题

我在使用 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; }
}

我希望这对您有所帮助。

From the looks of your class the ICollection properties are defining foreign key relationships? If so, you wouldn't want to be publicly exposing the collections.

For example: If you are following the best practices guide for developing Entity Framework models, then you would have a separate class called "Question" which would wire up your two class together which might look like the following:

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

If this was the case, you could quite possibly go round in circles calling the Question -> Survey -> ICollection -> Question

I had a similar incident using EF, MVC3 to implement a REST service and couldn't serialize the ICollection<> object then realised I didn't need to as I would be calling the object separately anyway.

The updated class for your purposes would look like this:

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

I hopes this helps you out.

太阳哥哥 2024-12-12 22:10:15

ICollection 更改为 List

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 List<Question> Questions { get; set; }
    public virtual List<SurveyResponse> SurveyResponses { get; set; }
}

Change the ICollection<T> to a List<T>

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 List<Question> Questions { get; set; }
    public virtual List<SurveyResponse> SurveyResponses { get; set; }
}
菊凝晚露 2024-12-12 22:10:15

如果您不介意添加对程序集 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());
        }
    }

If you don't mind adding a reference to the assembly System.Runtime.Serialization, you can utilize this code which will serialize an object with ICollection without needing to change the object's implementation. The code below is outputting to string. You can use the stream however you'd like.

    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());
        }
    }
玩世 2024-12-12 22:10:15

我使用了 Matthew Merryfull 解决方案,它有效。

由于每次更新模型时我都使用 EF 设计器来生成实体,因此我会失去手动更改。我必须更改用于生成模型的 *.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));
}

另请检查这篇文章,以防您遇到序列化问题 http://geekswithblogs.net/danemorgridge/archive/2010/05/04/entity-framework-4-wcf-amp-lazy-loading-tip.aspx

I used Matthew Merryfull solution and it works.

Since I am using EF designer for entity generation each time I update my models I would loose manual changes. I had to change *.tt which is used for generation of models. I edited few lines:

   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));
}

Also check this article in case you run into problem with serialization http://geekswithblogs.net/danemorgridge/archive/2010/05/04/entity-framework-4-wcf-amp-lazy-loading-tip.aspx

时光匆匆的小流年 2024-12-12 22:10:15

对我来说,问题在于没有默认构造函数。例子:
列出 MyVar; // MyClass 需要一个公共构造函数

For me the issue was not having a default constructor. Example:
List MyVar; // MyClass needs a public constructor

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文