2011-12-12 22 views
7

En nuestra aplicación de facturación en línea, ofrecemos un resumen de facturación de las facturas que recibió el cliente y los pagos que realizó.La entidad o tipo complejo no se puede construir en una consulta LINQ to Entities

Para que esto funcione, primero tengo que retirar los pagos y luego compararlos con las facturas. Así que he de hacer algo como:

foreach (BillPaymentSummary payment in billPayments) 
{ 
    DateTime dt = payment.DueDate; 

    // Debug errors on this next line 
    var summary = (from a in db.BillHistories 
        where a.CustomerId == customerNumber && a.DueDate == dt && a.Type == "BILL" 
        select new BillSummary 
        { 
         Id = a.Id, 
         CustomerId = a.CustomerId, 
         DueDate = a.DueDate, 
         PreviousBalance = a.PreviousBalance.Value, 
         TotalBill = a.TotalBill.Value, 
         Type = a.Type, 
         IsFinalBill = a.IsFinalBill 
        }).SingleOrDefault(); 

    if (summary != null) 
    { 
     summary.PayDate = payment.PaidDate; 
     summary.AmountPaid = payment.AmountPaid; 
     returnSummaries.Add(summary); 
    } 
    else 
    { 
     summary = (from a in db.BillHistories 
        where a.CustomerId == customerNumber && a.DueDate == payment.DueDate && a.Type == "ADJ " 
        select new BillSummary 
        { 
         Id = a.Id, 
         CustomerId = a.CustomerId, 
         DueDate = a.DueDate, 
         PreviousBalance = a.PreviousBalance.Value, 
         TotalBill = a.TotalBill.Value, 
         Type = a.Type, 
         IsFinalBill = a.IsFinalBill 
        }).SingleOrDefault(); 

     if (summary != null) 
     { 
      summary.PayDate = payment.PaidDate; 
      summary.AmountPaid = payment.AmountPaid; 
      returnSummaries.Add(summary); 
     } 
    } 
} 

He estado jugando con esto, pero no importa lo que hago, me sale el siguiente mensaje de error:

La entidad o tipo complejo 'UtilityBill.Domain .Concrete.BillSummary 'no se puede construir en una consulta LINQ to Entities.

¿Es porque estoy ejecutando consultas dentro de las consultas? ¿Cómo puedo evitar este error?

He intentado buscar en Google una respuesta y veo muchas respuestas, pero ninguna de ellas parece explicar mi problema.

+0

posible duplicado de [La entidad no puede ser construido en una consulta LINQ a Entidades] (http://stackoverflow.com/questions/5325797/the-entity- no se puede construir en una consulta de linq-a-entidades) – flipchart

Respuesta

6

No se puede proyectar en una entidad mapeada. Debería llamar al ToList() antes de hacer su mapeo.

O mejor aún, cambiar a la siguiente (FirstOrDefault llamando ejecutará la consulta y le permitirá rellenar el objeto):

var summary = db.BillHistories.FirstOrDefault(a => a.CustomerId == customerNumber && a.DueDate == dt && a.Type == "BILL").Select(x => new BillSummary 
           { 
            Id = a.Id, 
            CustomerId = a.CustomerId, 
            DueDate = a.DueDate, 
            PreviousBalance = a.PreviousBalance.Value, 
            TotalBill = a.TotalBill.Value, 
            Type = a.Type, 
            IsFinalBill = a.IsFinalBill 
           }); 

Para desvincular a sí mismo de Entity Framework es posible que desee también considerar el uso de una diferente clase de modelo para devolver en lugar del modelo de Entity Framework.

+0

Esto me llevó en la dirección correcta aunque no del todo la respuesta correcta. Quiero darte crédito. –

+0

@MikeWills gracias por el representante! Creo que sí señalé lo que estaba mal con tu código y cómo solucionarlo. – Craig

+1

@MikeWills eliminé mi edición que indicaba que al llamar 'Where' y luego' FirstOrDefault' provocaría que se generara SQL adicional ya que no parece ser el caso. Tal vez esto fue un problema en una versión anterior porque he estado siguiendo esta regla por bastante tiempo ... o tal vez fue solo información errónea. – Craig

0

Lo que terminé haciendo fue:

 foreach (BillPaymentSummary payment in billPayments) 
     { 
      var data = db.BillHistories.Where(b => b.CustomerId == customerNumber && b.DueDate == payment.DueDate && b.Type == "B").FirstOrDefault(); 

      if (data != null) // There is a bill history 
      { 
       returnSummaries.Add(new BillSummary 
       { 
        Id = data.Id, 
        CustomerId = data.CustomerId, 
        DueDate = data.DueDate, 
        PreviousBalance = data.PreviousBalance, 
        TotalBill = data.TotalBill, 
        Type = (data.Type.Trim() == "B" ? "BILL" : (data.Type == "A" ? "ADJ" : "")), 
        IsFinalBill = data.IsFinalBill, 
        PayDate = payment.PaidDate, 
        AmountPaid = payment.AmountPaid 
       }); 
      } 
      else // No bill history record, look for an adjustment 
      { 
       data = db.BillHistories.FirstOrDefault(b => b.CustomerId == customerNumber && b.DueDate == payment.DueDate && b.Type == "A"); 

       if (data != null) 
       { 
        returnSummaries.Add(new BillSummary 
        { 
         Id = data.Id, 
         CustomerId = data.CustomerId, 
         DueDate = data.DueDate, 
         PreviousBalance = data.PreviousBalance, 
         TotalBill = data.TotalBill, 
         Type = (data.Type.Trim() == "B" ? "BILL" : (data.Type == "A" ? "ADJ" : "")), 
         IsFinalBill = data.IsFinalBill, 
         PayDate = payment.PaidDate, 
         AmountPaid = payment.AmountPaid 
        }); 
       } 
      } 
      db.SaveChanges(); 
     } 
+0

Creo que es una solución terrible. Asignación manual de tipos anónimos a las clases de entidades definidas. Sin embargo, no te juzgué ... también me siento como si Microsoft lo dejara bajo la lluvia ... Si quieres usar un ORM, quieres que llene el espacio entre los datos relacionales y las clases de entidad. Esto no es lo que está sucediendo aquí. – ckonig

Cuestiones relacionadas