返回实体框架中的普通对象以进行序列化

时间:2009-04-04 08:31:00

标签: linq-to-sql json entity-framework serialization poco

我在ASP.NET MVC应用程序中尝试过Linq to Sql和EF。切换到EF后,我意识到我的XML / JSON序列化输出有额外的瑕疵。

XML:

<Test xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <EntityKey>
    <EntitySetName>Persons</EntitySetName>
    <EntityContainerName>PersonEntities</EntityContainerName>
    <EntityKeyValues>
      <EntityKeyMember>
        <Key>Id</Key>
        <Value xsi:type="xsd:int">1</Value>
      </EntityKeyMember>
    </EntityKeyValues>
  </EntityKey>
  <Id>1</Id>
  <Name>John</Name>
</Test>

JSON:

{"Id":1,"Name":"John","EntityState":2,"EntityKey"{"EntitySetName":"Persons","EntityContainerName":"PersonEntities","EntityKeyValues":[{"Key":"Id","Value":1}],"IsTemporary":false}}

相反,我只想输出:

{"Id":1, "Name":"John"}

我检索对象的EF查询是:

Tests.First(t => t.Id == testId);

3 个答案:

答案 0 :(得分:7)

您可以在控制器中塑造JSON结果,如下所示:

public JsonResult Person(int id)
{
  var person = PersonRepository.FindByID(id);
  var result = new { Id = person.Id, Name = person.Name };
  return Json(result);
}

这将限制序列化的DTO仅包含您想要的值。

编辑: 作为评论问题的一个回答;您可以创建一个更简单的PersonViewModel类(DTO),您可以将属性映射到。正如John Saunders在他的回答中提到的,Automapper是一种简化从EF Person实例复制属性值的好方法:

修改后的Action方法可能如下所示:

public JsonResult Person(int id)
{
  var person = PersonRepository.FindByID(id);
  var dto = Mapper.Map<Person, PersonViewModel>(person);
  return Json(dto);
}

我能想到的唯一另一个选择是使用反射来修改Person实体上的DataMemberAttributes以抑制EntityKey属性。

答案 1 :(得分:5)

解决此问题的另一种方法是使用JavascriptSerializer的ScriptIgnore属性并为相关对象创建一个分部类,新建EntityKey,EntityState属性并向其添加ScriptIgnore属性:

public partial class Person
{
    [ScriptIgnore]
    public new System.Data.EntityKey EntityKey { get; set; }

    [ScriptIgnore]
    public new System.Data.EntityState EntityState { get; set; }
}

当通过JavascriptSerializer序列化Person类时,它将忽略这些属性。但是,这不实用,因为EF使用状态信息来跟踪对象,这会造成严重破坏。

如果有一种方法可以动态添加属性,那么只需添加[ScriptIgnore]属性就不需要覆盖这些属性。但是,由于无法动态添加属性,因此该解决方案可能没那么有用。

答案 2 :(得分:1)

到目前为止,我发现的最好的技术涉及代码生成。我在一个使用Service Factory的项目上执行了此操作,但您可以直接使用T4 Text templates“手动”执行此操作。

另外,请留意AutoMapper。它仍然是新的,我认为它是新兴技术,但我希望它很快就会出现!

相关问题