6

Contexto:Uso de propiedades de navegación de código marco de la entidad primeros

  • Código En primer lugar, Entity Framework 4.3.1;
  • Usuario ---- Tema, 1 a Muchos relación;
  • User con public virtual ICollection<Topic> CreatedTopics Propiedad de navegación (Lazy Loading);
  • Topic con public virtual User Creator Propiedad de navegación;
  • DataServiceController : DbDataController<DefaultDbContext>, Web API beta, ASP.NET MVC 4 Beta, Aplicación de una sola página;
  • System.Json for Json serialization;
  • Web API Acción:

    public IQueryable<Topic> GetTopics() 
    { 
        // return DbContext.Topics;     // OK 
        return DbContext.Topics.Include("Creator"); //With Exception 
    } 
    
  • Resultado: "una excepción Microsoft .NET Framework no controlada en w3wp.exe"

El problema aquí parece ser: lo que debería no Agregar propiedad de navegación en ambas entidades (¿Referencia circular de la causa?), y si elimino la propiedad de navegación CreatedTopics en User Clase, lo hará estar bien de nuevo

Así, en un contexto similar análogos enumerados, aquí están mis preguntas:

  1. ¿Cómo lidiar con las propiedades de navegación en la situación de 1 a Muchos relación;
  2. Además, ¿qué tal un Muchos a muchos relación, tengo que dividirlo en dos 1 a muchas relaciones;
  3. ¿Cuáles son las mejores prácticas y precauciones para usar las propiedades de navegación?

He leído muchos mensajes relacionados, pero todavía no lo suficientemente claras :(,

Gracias por cualquier ayuda

Dean

Respuesta

9

Esto no es un problema de código primero o EF! - es un problema de serialización. Simplemente el serializador utilizado para convertir su gráfico de objetos a una representación pasada en un mensaje de API Web no puede trabajar con referencias circulares de manera predeterminada. Dependiendo del formato del mensaje que desea usar, la API Web utiliza diferentes serializadores. por defecto - here es más una sobre los serializadores predeterminados utilizados por la API web y sobre la forma de cambiarlo. El siguiente texto supone que está utilizando DataContractJsonSerializer o DataContractSerializer (debe ser el predeterminado para la serialización XML) pero lo mismo es posible para JSON.NET (debe ser por defecto la serialización JSON; la serialización JSON puede cambiarse a DataContractJsonSerializer pero el serializador predeterminado es mejor) .

¿Qué puedes hacer?Puede decirle al serializador que debe rastrear esas referencias circulares marcando sus clases con DataContract(IsReference = true) y cada propiedad pasada con el atributo DataMember (consulte el artículo vinculado para obtener una descripción de cómo lograrlo con JSON.NET). Esto permitirá que el serializador reconozca correctamente los ciclos y, en teoría, la serialización tendrá éxito. En teoría, porque esto también exige no usar cargas perezosas. De lo contrario, puede serializar muchos más datos de los que esperaba (en algunos escenarios catastróficos puede llevar a serializar todo el contenido de su base de datos).

al serializar gráfico entidad con carga diferida permitió que serailze un Topic y su Creator pero serialización también visitará CreatedTopics propiedad => todos los temas relacionados son perezosos cargado y procesado por la serialización y la serialización continúa visitando Creator de todos los temas recién cargadas ! Este proceso continúa hasta que no haya otro objeto para la carga lenta. Debido a esto, nunca debes usar la carga diferida al serializar entidades.

Otra opción es excluir la referencia de la serialización. Solo necesita serializar Creator. No necesita serializar CreatedTopics para marcar la propiedad con el atributo IgnoreDataMember (JsonIgnore para JSON.NET). El problema es que si también tiene una acción Web API para devolver User con todos sus CreateTopics, esto no funcionará debido al atributo.

La última opción es no usar entidades. Esta opción se usa generalmente en servicios web donde se crean objetos DTO especiales que satisfacen los requisitos para una operación específica y se maneja la conversión entre entidades y DTO dentro de la operación (es posible con la ayuda de alguna herramienta como AutoMapper).

No hay diferencia entre las relaciones de uno a uno, de uno a muchos o de muchos a muchos. Si tiene propiedades de navegación en ambos lados, siempre debe tratar este problema.

+0

¿DataContractJsonSeriaizer es el serializador Json predeterminado para Web API Beta? – Dean

+0

Estoy usando 'DataContract (IsReference = true)' y 'DataMember' temporalmente, ¿hay algún artículo detallado sobre esto? También estoy interesado en la opción de DTO, pero no lo logré, pasaré más tiempo y agradezco la buena respuesta. – Dean

Cuestiones relacionadas