簡體   English   中英

渴望在asp.net Web API中加載

[英]Eager Loading in asp.net web api

嗨,社區,我最近開始學習如何編寫網絡api,

我在winform中有一個項目想要使用Web api進行重新制作,但問題是我無法使用緊急加載,我總是收到錯誤500,代碼如下:

public HttpResponseMessage GetExpediente()
    {
        db.Configuration.ProxyCreationEnabled = false;
        var expediente = db.Expediente.Include(x=>x.Documento);
        if (expediente.Any())
        {
            return Request.CreateResponse(HttpStatusCode.OK, expediente);
        }
        else
        {
            return Request.CreateErrorResponse(HttpStatusCode.NotFound,
                "No se encontraron expedientes.");
        }
    }

我總是得到的錯誤是:

{"Message":"An error has occurred.","ExceptionMessage":"The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.","ExceptionType":"System.InvalidOperationException","StackTrace":null,"InnerException":{"Message":"An error has occurred.","ExceptionMessage":"Self referencing loop detected for property 'Expediente' with type 'Modelo.Expediente'. Path '[0].Documento[0]'.","ExceptionType":"Newtonsoft.Json.JsonSerializationException","StackTrace":"   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CheckForCircularReference(JsonWriter writer, Object value, JsonProperty property, JsonContract contract, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.CalculatePropertyValues(JsonWriter writer, Object value, JsonContainerContract contract, JsonProperty member, JsonProperty property, JsonContract& memberContract, Object& memberValue)\r\n   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeObject(JsonWriter writer, Object value, JsonObjectContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeList(JsonWriter writer, IEnumerable values, JsonArrayContract contract, JsonProperty member, JsonContainerContract collectionContract, JsonProperty containerProperty)\r\n   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)\r\n   en Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)\r\n   en Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)\r\n   en System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)\r\n   en System.Net.Http.Formatting.JsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, Encoding effectiveEncoding)\r\n   en System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStream(Type type, Object value, Stream writeStream, HttpContent content)\r\n   en System.Net.Http.Formatting.BaseJsonMediaTypeFormatter.WriteToStreamAsync(Type type, Object value, Stream writeStream, HttpContent content, TransportContext transportContext, CancellationToken cancellationToken)\r\n--- Fin del seguimiento de la pila de la ubicación anterior donde se produjo la excepción ---\r\n   en System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   en System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   en System.Web.Http.WebHost.HttpControllerHandler.<WriteBufferedResponseContentAsync>d__1b.MoveNext()"}}

我一直在尋找信息。 那可以幫助我,但我總是發現我應該禁用延遲加載,但我確實做到了,但沒有成功,這里有人可以幫助我嗎?

順便說一句,我的目標是從Windows窗體項目中使用此api,有人告訴我這樣做:

var emp1 = response.Content.ReadAsStringAsync().Result;
        var result = JsonConvert.DeserializeObject<IEnumerable<ExpedientePOCO>>(emp1);

但是我從var emp1 = ...的行中得到的錯誤500。哦,當我從上下文中獲取include時,它的工作正常,但是我想使用Eager加載,希望對您有所幫助!

謝謝! 問候!

我對DTO的了解:

 public HttpResponseMessage GetExpediente()
    {
        db.Configuration.ProxyCreationEnabled = false;
        var expediente = db.Expediente.Include(x=>x.Documento);
        List<ExpedientePOCO> expPOCO = new List<ExpedientePOCO>();
        foreach (var entidad in expediente)
        {
            String fecha = String.Format("{0:dd-MM-yyy}", entidad.FechaCreacion);
            ExpedientePOCO expedientePOCO = new ExpedientePOCO()
            {
                idExpediente = entidad.idExpediente,
                NombreExpediente = entidad.NombreExpediente,
                FechaCreacion = Convert.ToDateTime(fecha),
                DuenioExpediente = entidad.DuenioExpediente,
                CantidadDocumento = entidad.CantidadDocumento
            };
            foreach (var documentos in entidad.Documento)
            {
                DocumentoPOCO documento = new DocumentoPOCO()
                {
                    idDocumento = documentos.idDocumento,
                    idExpediente = documentos.idExpediente,
                    NombreDocumento = documentos.NombreDocumento,
                    FechaCreacion = documentos.FechaCreacion,
                    Expedientes = expedientePOCO
                };
                expedientePOCO.Documentos.Add(documento);
            }
            expPOCO.Add(expedientePOCO);
        }
        if (expPOCO.Any())
        {
            return Request.CreateResponse(HttpStatusCode.OK, expPOCO);
        }
        else
        {
            return Request.CreateErrorResponse(HttpStatusCode.NotFound,
                "No se encontraron expedientes.");
        }
    }

問題是,如錯誤消息所述,您有一個無限循環,很可能是這樣的:

public class A
{
    public B B { get; set; }
}

public class B
{
    public virtual ICollection<A> A { get; set; }
}

因此,您A => B => A無休止地得到A => B => A ,因此會出現錯誤。 您可以通過配置串行(解決這個ReferenceLoopHandling.Ignore ,或通過使用屬性(在NewtonSoft.Json) [JsonIgnore]根據您的具體需求和工具使用。

另一個解決方案是使用數據傳輸對象(DTO)或類似的方法:

public class ADTO
{
    // needed properties only
    public BDTO B { get; set; }
}

public class BDTO
{
    // needed properties only
    public List<ADTO> A { get; set; }
}

然后選擇DTO而不是實體:

var data = db.As
    .Select(a => new ADTO 
    {
        x = a.x ....
        B = new BDTO { x = a.B.x ...  }
    }
    .ToList();

或者,反過來:

var data = context.B
    .Select(b => new BDTO
    {
        x = b.x ...
        A = b.A
            .Select(a => new ADTO
            {
                x = a.x ...
            }
            .ToList()
    }
    .ToList();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM