2012-11-05 3 views
2

내 코드에 문제가 있습니다. 일부 기본 키 (외부 키가없는 3 개 필드)에서 작동하는 웹 컨트롤러가 있지만 모델에서 개체 목록을 반환하는 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 (inspect)를 넣고 목록의 객체 유형을 MaestroProvincia 유형 대신 system.data.entity.DynamicProxies.MaestroProvincia_D7543654378543이 아닌 매우 이상합니다.

FK가없는 모델에서 개체를 반환하는 다른 모든 API 컨트롤러는 문제가 없습니다.

귀하의 도움에 감사드립니다.

답변

0

EF를 모델 우선 또는 데이터베이스 우선 접근 방식으로 사용하고있는 것처럼 보입니다. EF는 외부 키를 사용하여로드 종속 ​​테이블을 지연시킬 수있는 동적 프록시를 반환합니다. 동적 프록시를 직렬화 할 수 없습니다. API는 결과를 반환하는 데 필요합니다. 일반적으로 EF 엔티티를 직접 반환하는 것은 좋지 않습니다. 순수 POCOSdata transfer objects (DTO)을 사용해야합니다.

순수 POCOS는 사용자가 자신을 정의한 클래스를 의미하지만 엔티티를 모방하지만 클라이언트가 요구하는 데이터 만 반환합니다. 때로는 순수 POCOS이고 때로는 동적 프록시이기 때문에 T4 템플릿을 사용하여 EF에서 생성 한 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을 실행해야합니까? 매퍼 직전에. 맵에서 또는 코드의 다른 위치에서 한 번만 할 수 있습니까? – user1800750

0

을 사람들은에 Entityy 프레임 워크에 의해 생성 된 프록시입니다 게으른로드를 용이하게합니다. 그러나 그것은 당신의 도메인 모델이 가진 모든 장점을 가질 것입니다. 당신이해야 할 일은 그 클래스의 데이터를 읽고 ViewModels (POCO 클래스)를 공용 세계로 반환하는 것입니다. 이 아닌 도메인 모델을 공용 세계로 반환하는 것이 좋습니다. 사람들은 당신의 표가 어떻게 생겼는지 알아낼 수 있습니다.

외부 세계로 데이터를 반환하기 위해 ViewModels (POCO 클래스)을 만듭니다. 돌아올 필요가있는 재산 만 소유하십시오. 도메인 모델의 모든 속성을 항상 사용자의 뷰 모델에 포함 할 필요는 없습니다.나중에 데이터 액세스에서 데이터를 가져 와서 항목을 읽고이를 뷰 모델의 인스턴스에 매핑 한 다음 반환하십시오. Mastero 가정

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 

는 POCO 클래스, 당신의 ViewModel입니다.

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

고마워요, 이해했는데, 그렇다면 다른 POCO 클래스로 전체 도메인을 반복해야합니까?. – user1800750

+0

@ user1800750 : 전체 도메인 모델이 아닙니다. 대중에게 돌아가고 싶은 것만. 도메인 모델을 프론트 엔드에 묶는 것은 좋은 생각이 아닙니다. – Shyju

관련 문제