2012-11-05 49 views
2

我的代码存在问题。 我有一些基本的WEB API控制器工作正常(三个字段没有任何外键),但我有一个API控制器的问题,从模型返回对象的列表,该类有一个外键到另一个类从该模型。 这将引发一个错误: 这里是API控制器:使用带有外键的对象返回带有WEB API控制器的JSON

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控制器没有任何问题。

我将不胜感激您的帮助。

回答

0

它看起来像你使用EF与模型优先或数据库优先的方法。 EF正在返回动态代理,通过使用外键允许您延迟加载相关表。你不能序列化动态代理,这将是你的API返回结果所必需的。直接返回您的EF实体通常不是一个好习惯。您应该使用data transfer objects (DTO),而不是纯粹的POCOS

纯粹的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); 
+0

我该怎么做?我认为带有db.MaestroProvincia.AsEnumerable的EF已经返回了一个POCO实体列表。 – user1800750

+0

我已经更新了我的答案,告诉你如何做到这一点。 –

+0

非常感谢,最后一个问题,我应该何时执行Mapper.createmap?就在Mapper.Map之前,或者我可以在代码的另一个地方做一次? – user1800750

0

这些都是由Entityy框架创建到代理方便延迟加载。但它会拥有你的领域模型的所有功能。你应该做的是从这些类中读取数据并将ViewModel(POCO类)返回给公共领域。它是而不是是一个好主意,可以将您的域模型返回到公共领域。人们可以根据自己的表格了解你的餐桌。

创建视图模型(POCO类)将数据返回到外部世界。只有返回必需的资产。您无需在视图模型中随时保留域模型的所有属性。稍后从数据访问中获取数据,读取项目,将其映射到viewmodel的实例并返回。

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类,你的viewmodel。

public class Mastero 
{ 
    public string Name { set;get;} 
    public string Description { set;get;} 
} 
+0

Thankyou,我明白了,但是我不得不重复整个领域与另一个POCO类呢? – user1800750

+0

@ user1800750:不是整个域模型。只有你想要回到公众。将领域模型与前端绑定并不是一个好主意, – Shyju