4

我一直在我的 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);
4

3 回答 3

8

您可以像这样在控制器中塑造 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 中提到的那样,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 属性。

于 2009-04-04T09:04:01.790 回答
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; }
}

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

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

于 2009-04-05T12:42:41.210 回答
1

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

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

于 2009-04-04T11:42:22.470 回答