6

Contesto:utilizzando le proprietà di navigazione a entità codice del framework primi

  • Codice In primo luogo, Entity Framework 4.3.1;
  • Utente ---- Argomento, da 1 a molti relazione;
  • User con public virtual ICollection<Topic> CreatedTopics Proprietà di navigazione (Caricamento pigro);
  • Topic con public virtual User Creator Proprietà di navigazione;
  • DataServiceController : DbDataController<DefaultDbContext>, API Web beta, Beta MVC 4 ASP.NET, Applicazione pagina singola;
  • System.Json per serializzazione Json;
  • Web API Azione:

    public IQueryable<Topic> GetTopics() 
    { 
        // return DbContext.Topics;     // OK 
        return DbContext.Topics.Include("Creator"); //With Exception 
    } 
    
  • Risultato: "un'eccezione non gestita .net framework di Microsoft si è verificato in w3wp.exe"

Il problema qui sembra essere: dovrei non Aggiungi proprietà di navigazione in entrambe le entità (causa riferimento circolare?) e se elimino la proprietà di navigazione CreatedTopics nella classe User, verrà va bene di nuovo.

Quindi, in un contesto simile come elencati sopra, Ecco le mie domande:

  1. Come comportarsi con proprietà di navigazione nella situazione di 1 a molti relazione;
  2. Inoltre, che ne dite di un rapporto da molti a molti, devo dividerlo in due da 1 a molte relazioni;
  3. Quali sono le migliori pratiche e precauzioni per l'utilizzo delle proprietà di navigazione?

Ho letto molti post correlati, ma ancora non abbastanza chiare :(,

Grazie per qualsiasi aiuto

Dean

risposta

9

Questo non è un problema di codice di primo o EF! - è un problema di serializzazione: semplicemente il serializzatore utilizzato per convertire il tuo oggetto grafico in una rappresentazione passata in un messaggio API Web non è in grado di funzionare con riferimenti circolari per impostazione predefinita, in base al formato del messaggio che desideri utilizzare. per impostazione predefinita - here è più a Segnala i serializzatori predefiniti utilizzati da Web API e spiega come modificarlo. Il seguente testo suppone che tu stia usando DataContractJsonSerializer o DataContractSerializer (dovrebbe essere l'impostazione predefinita per la serializzazione XML) ma lo stesso è possibile per JSON.NET (dovrebbe essere predefinito per la serializzazione JSON - La serializzazione JSON può essere passata a DataContractJsonSerializer ma il serializzatore predefinito è migliore) .

Quindi cosa si può fare?È possibile indicare al serializzatore di tenere traccia di tali riferimenti circolari contrassegnando le classi con DataContract(IsReference = true) e ogni proprietà passata con l'attributo DataMember (consultare l'articolo collegato per la descrizione su come ottenerlo con JSON.NET). Ciò consentirà al serializzatore di riconoscere correttamente i cicli e in teoria la serializzazione avrà successo. In teoria perché questo richiede anche di non usare il caricamento pigro. Altrimenti è possibile serializzare molti più dati di quanto previsto (in alcuni scenari catastrofici può portare alla serializzazione di tutto il contenuto del database).

quando si serializza grafico un'entità con caricamento pigro abilitato si serailze un Topic e la sua Creator ma serializzazione anche visitare CreatedTopics property => tutti gli argomenti correlati sono pigri caricato e trattati da serializzazione e la serializzazione continua a visitare Creator di tutti gli argomenti appena caricato ! Questo processo continua finché non ci sono altri oggetti a carico lento. Per questo motivo non si dovrebbe mai usare il caricamento lazy durante la serializzazione delle entità.

Un'altra opzione è escludere il riferimento di ritorno dalla serializzazione. Hai solo bisogno di serializzare Creator. Non è necessario serializzare CreatedTopics in modo da poter contrassegnare la proprietà con l'attributo IgnoreDataMember (JsonIgnore per JSON.NET). Il problema è che se si dispone anche dell'azione API Web per la restituzione di User con tutto il suo CreateTopics, ciò non funzionerà a causa dell'attributo.

L'ultima opzione non utilizza le entità. Questa opzione viene solitamente utilizzata nei servizi Web in cui si creano oggetti DTO speciali che soddisfano i requisiti per operazioni specifiche e si gestisce la conversione tra entità e DTO all'interno dell'operazione (possibile con l'aiuto di alcuni strumenti come AutoMapper).

Non c'è differenza tra la gestione delle relazioni uno a uno, uno a molti o molti a molti. Se disponi di proprietà di navigazione su entrambi i lati, devi sempre risolvere questo problema.

+0

DataContractJsonSeriaizer è il Serializzatore Json predefinito per Beta API Web? – Dean

+0

Sto usando 'DataContract (IsReference = true)' e 'DataMember' temporaneamente, c'è un articolo dettagliato che parla di questo? Sono anche interessato all'opzione DTO, ma per ora non sono riuscito a farcela, dedicherò più tempo a questo, e grazie per la buona risposta. – Dean

Problemi correlati