在LINQ to Entities查询中,无法构造实体或复杂类型

7
我们的在线账单应用程序会给客户提供账单汇总和付款情况。为了实现这一功能,我需要先获取付款信息,然后匹配账单。所以我需要做如下操作:
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);
        }
    }
}

我一直在尝试使用它,但无论我做什么,都会得到以下错误消息:

不能在LINQ to Entities查询中构造实体或复杂类型'UtilityBill.Domain.Concrete.BillSummary'。

这是因为我在查询中运行了查询吗?我该如何避免这个错误?

我已经尝试在Google上搜索答案并看到很多答案,但没有一个似乎能解释我的问题。


2个回答

6
您不能将内容映射到已映射的实体上。在进行映射之前,您需要调用 ToList() 方法。

或者更好的方法是更改为以下内容(调用 FirstOrDefault 将执行查询并允许您填充对象):

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
                               });

要想与Entity Framework解耦,您可能还需要考虑使用不同的模型类来返回,而不是使用Entity Framework模型。


这让我朝着正确的方向前进,虽然不完全是正确的答案。我想要给你点赞。 - Mike Wills
@MikeWills 感谢赞!我认为我指出了你代码中的问题以及如何修复它。 - Craig
1
@MikeWills 我删除了我的编辑,因为它表明调用 Where 然后再调用 FirstOrDefault 会导致额外的 SQL 生成,但事实并非如此。也许这在早期版本中存在问题,因为我已经遵循这个规则有一段时间了...或者可能只是错误信息。 - Craig

0
我最终做的是:
        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();
        }

我认为那是一个可怕的解决方案。手动映射匿名类型到已定义的实体类。不过我不会评判你...我也感觉被微软抛弃了...如果你想使用ORM,你希望它填补关系数据和实体类之间的差距。但这并不是在这里发生的事情。 - ckonig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接