2

我的代码有问题。我有一些基本的 WEB API 控制器可以正常工作(三个字段没有任何外键),但是我有一个 API 控制器的问题,它从模型中返回一个对象列表,并且该类具有另一个类的外键模型。这会引发错误:这是 Api 控制器:

Public Class MaestroProvinciaController
    Inherits System.Web.Http.ApiController

    Private db As New UnificadorEntities

    ' GET api/MaestroProvincia
    Function GetMaestroProvincias() As IEnumerable(Of MaestroProvincia)
        Dim l As IEnumerable(Of MaestroProvincia)
        l = db.MaestroProvincia.AsEnumerable()
        Return l
    End Function
End Class

这是 MaestroProvincia 的模型

Partial Public Class MaestroProvincia
  Public Property Codigo As Integer
  Public Property Descripcion As String
  Public Overridable Property Usuario As ICollection(Of Usuario) = New HashSet(Of Usuario)

End Class

当我消费,尝试,从浏览器到这个地址: ......../api/maestroprovincia

我收到一个错误: Error del servidor El sistema encontró un error mientras extraía ......../api/maestroprovincia . Es posible que el servidor no esté disponible por mantenimiento o no esté bien configurado. A continuación se detallan algunas sugerencias: Volver a cargar esta página web después. Error HTTP 500 (Internal Server Error): Se encontró una situación inesperada mientras el servidor intentaba cumplir con la solicitud.

当我调试控制器时,在"l"变量中放了一个 WATCH(检查),并且列表对象的类型很奇怪,而不是MaestroProvincia我得到的类型system.data.entity.DynamicProxies.MaestroProvincia_D7543654378543

从没有 FK 的模型返回对象的所有其他 API 控制器没有任何问题。

我会很感激你的帮助。

4

2 回答 2

0

看起来您正在使用模型优先或数据库优先方法的 EF。EF 正在返回动态代理,允许您使用外键延迟加载依赖表。您不能序列化动态代理,您的 API 需要它来返回结果。直接返回您的 EF 实体通常不是一个好习惯。您应该改用纯POCOS的数据传输对象 (DTO)

我所说的纯 POCOS 是指您自己定义的类,它们模仿实体但只返回客户端所需的数据。您不能使用 EF 使用 T4 模板生成的 POCOS,因为它们有时是纯 POCOS,有时它们是动态代理。将实体转换为 DTO 的方法是为实体中的属性创建一个使用相同名称的类,并且只包括客户端使用的那些属性。我通常将 DTO 放在单独的命名空间中,以将它们与实体区分开来。然后使用Automapper自动将实体映射到 DTO 和 DTO 到返回的实体。Automapper 从映射过程中消除了苦差事。只需一行代码即可创建地图:

Mapper.CreateMap<Entity.MaestroProvincia, DTO.MaestroProvincia>();

然后只需要另一行代码来执行实际的映射:

DTO.MaestroProvincia dto = Mapper.Map<Entity.MaestroProvincia, DTO.MaestroProvincia>(maestroProvincia);
于 2012-11-05T21:48:21.767 回答
0

这些是 Entityy Framework 为促进延迟加载而创建的代理。但它将具有您的域模型所具有的所有属性。您应该做的是从这些类中读取数据并将您的 ViewModel(POCO 类)返回到公共世界。将域模型原样返回公共世界并不是一个好主意。人们可以从中找出您的桌子的样子。

创建用于将数据返回到外部世界的 ViewModel(POCO 类)。只拥有返回所必需的属性。您不需要一直在视图模型中拥有域模型的所有属性。稍后从您的数据访问中获取数据,读取项目,将其映射到您的视图模型的实例并返回它。

List<Mastero> masteroList=new List<Mastero>();
var domainItems=db.MaestroProvincia.AsEnumerable();
foreach(var item in domainItems)
{
  var vm=new Mastero();
  vm.Name=item.Name;
  vm.Description=item.Description;
  masteroList.Items.Add(vm);
}  
 //Now return masteroList to the public

假设Mastero是一个 POCO 类,你的视图模型。

public class Mastero
{
  public string Name { set;get;}
  public string Description { set;get;}
}
于 2012-11-05T21:58:05.350 回答