11

Me estoy rompiendo la cabeza por este problema. Encontré algo en Internet al respecto, pero no una respuesta clara. Mi problema:WebApi con código EF Primero genera un error al tener la relación padre-hijo

tengo a clases en la sección Modelo de una aplicación MVC3 web: ParentClass y ChildClass En ParentClass hay una propiedad Hijos de tipo List

que utilicé Código EF En primer lugar, lo que genera claramente un padre tabla y una tabla hija para mí en la base de datos.

Ahora necesito un servicio REST que devuelva una lista o una sola clase principal.

Cuando elimino la propiedad Children from the ParentClass no hay ningún problema. Pero con la Propoerty Children there sigo recibiendo un error.

error: "The type System.Data.Entity.DynamicProxies.ParentClass_A0EBE0D1022D01EB84B81873D49DEECC60879FC4152BB115215C3EC16FB8003A was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically."}

Algunos código:

Clases:

 public class ParentClass 
{ 
    public int ID { get; set; } 
    public string Name {get;set;} 
    public virtual List<ChildrenClass> Children { get; set; } 

} 

public class ChildrenClass 
{ 
    public int ID { get; set; } 
    public string MyProperty { get; set; } 
} 

Servicio:

[ServiceContract] 
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] 
[ServiceBehavior(IncludeExceptionDetailInFaults = true)] 
public class MyService 
{ 

    static MyContext db; 
    public MyService() { db = new MyContext(); } 


    [WebGet(UriTemplate = "")] 
    public List<ParentClass> GetParents() 
    { 
     var result = db.Parents.ToList(); 
     return result; 

    } 

no voy a obtener el resultado cuando callinh este servicio. ¿Qué estoy haciendo mal?

Respuesta

12

tuve que DisableProxyCreation en la configuración contexto:

[OperationContract] 
[WebGet(UriTemplate = "")] 
public List<ParentClass> GetParents() 
{ 
    using (DBContext context = new DBContext()) 
    { 
     context.Configuration.ProxyCreationEnabled = false; 
     List<ParentClass> parents = context.Parents 
      .Include("Children") 
      .ToList(); 
     return parents; 
     } 
} 

Esto funcionó muy bien para mí.

+0

Justo lo que estaba buscando. ¿Conoces algún inconveniente de deshabilitar esto? – hooked82

+1

Hay muchas cosas buenas de Proxies, haciendo un seguimiento de las actualizaciones y demás. No hay errores por olvidar incluir declaraciones. Todavía no tengo soluciones para serializar entidades proxi –

0

Parece que está serializando las clases de proxy para sus POCO, mi primera recomendación sería usar el proxydatacontractresolver: http://msdn.microsoft.com/en-us/library/system.data.objects.proxydatacontractresolver.aspx.

También me gustaría trabajar en tener cosas explicadas de forma explícita al cargar los datos para el envío de más de un servicio web ... es decir

Cambio de clase de padres a

public class ParentClass 
{ 
    public int ID { get; set; } 
    public string Name {get;set;} 
    public List<ChildrenClass> Children { get; set; } 

} 

alterar su contenido para desactivar la carga diferida: Disable lazy loading by default in Entity Framework 4

Y explícitamente especifique qué desea cargar al devolver los datos que se envían a través del cable.

[WebGet(UriTemplate = "")] 
public List<ParentClass> GetParents() 
{ 
    var result = db.Parents.Include("Children").ToList(); 
    return result; 

} 

Tener un vistazo a la siguiente respuesta: Entity Framework Code First - Eager Loading not working as expected? durante más avanzadas incluyen llamadas.

También como consejo por experiencia, no devolvería sus clases de datos por cable ya que forman un contrato para el consumidor de su servicio web. Lo mejor es tener otro conjunto de clases en las que asigne los valores de los datos.

De esta forma, si cambian sus clases de datos, no tiene que cambiar el cliente del servicio web a menos que se requiera explícitamente.

Y el uso de paginación es importante si usted está esperando 1000 de las filas de las clases padre o hijo de otro modo se termina con N + 1 selecciona, consulte: What is SELECT N+1?.

+1

He intentado el DataContractResolver, pero eso no me ayudó. El disableproxycreation ayudó. Pero si lo entiendo correctamente, debería separar los POCO llenados de la base de datos de las clases para usar en los servicios. Pero eso no quiere decir que cada objeto deba duplicarse, lo que significa una clase principal para el uso dentro del sitio y la lógica de negocios y una clase secundaria separada para su uso en el servicio. ¿No es eso demasiado código de duplicación? – Mounhim

+0

Estamos utilizando DTO's y Automapper para separar nuestro modelo de recursos de nuestro modelo de dominio. Hay muchas ventajas en esto, incluyendo la validación por separado y las estructuras separadas/diferentes. – suing

+0

A menudo es excesivo duplicar sus POCO para N diferentes usos, incluido el trabajo adicional y el mantenimiento de maps/xlats. Muchos desarrolladores toman el enfoque de definir cuidadosamente sus POCO una vez y luego usarlos tanto para la transferencia de datos como para el acceso a los datos, especialmente en proyectos más pequeños. Si llega un momento en que esto ya no funciona (cambios de esquema, refactores, etc.), se deben definir nuevos POCO y se deben realizar los mapas necesarios. Este tipo de cambio/refactorización no afecta en absoluto a los clientes web, solo es realmente un problema para los consumidores de .NET de bibliotecas de clases. P.ej. dependientes binarios. –

0

En algunas situaciones, una solución simple es usar una clase contenedora para que todas las propiedades expuestas sean tipos conocidos.

Normalmente, no utilizará ObjectContext o DbContext en las clases de controlador, por lo que en una capa anterior (Business o Service) puede realizar una traducción rápida de los objetos procedentes de la base de datos a objetos de estilo ViewModel. similar a lo que harías en una aplicación MVC, pero en lugar de pasarlos a una Vista, los devuelves a la persona que llama.

Quizás no pueda usarlo en todos los casos, pero a menudo es un compromiso viable.

Cuestiones relacionadas