首页 > 解决方案 > EF Core 错误:“不支持比较实体类型,因为它是无键实体”进行外部联接时

问题描述

我有两张桌子。一份用于发票,一份用于付款。发票表具有这样的架构。

public class Invoice
{
  public Guid ID {get;set;}
  public string InvoiceNum {get;set;}
  public decimal Amount {get;set;}  
}

付款表具有这样的架构。

public class Payment
{
  public Guid ID {get;set;}
  public InvoiceID {get;set;}
  public decimal PaidAmount {get;set;}
  public DateTimeOffset? VoidDate {get;set;}
  public virtual Invoice Invoice { get; set; }
}

我想获得所有尚未全额支付的发票。首先,我声明了一个名为 PaymentStatus 的实体。

public class PaymentStatus
{
  public Guid InvoiceID {get;set;}
  public decimal TotalPaidAmount {get;set;}
}

然后在我的 DbContext 类中,我有

public virtual DbSet<Invoice> Invoices { get; set; }

public virtual DbSet<PaymentStatus> PaymentStatuses { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
            modelBuilder.Entity<PaymentStatus>().ToQuery(() =>
                Payment.Where(r => r.VoidDate == null)
                    .GroupBy(r => r.InvoiceID)
                    .Select(r => new PaymentStatus{ InvoiceID = r.Key, TotalPaidAmount = r.Sum(p => p.PaidAmount) }))
                .HasNoKey()
                .HasOne(r=>r.Invoice)
                .WithOne().HasForeignKey<PaymentStatus>(r=>r.InvoiceID);
}

然后我尝试通过外部加入 Invoices 和 PaymentStatuses 来获取未付发票的列表。

public Task<List<Receivables>> GetReceivables()
{
  var qry = from inv in MyDbContext.Invoices
    from pay in MyDbContext.PaymentStatuses.Where(p => p.InvoiceID == inv.ID).DefaultIfEmpty()
    select new Receivables
    {
      InvoiceID = inv.ID,
      InvoiceAmount = inv.Amount,
      PaidAmount = pay==null ? 0 : pay.TotalPaidAmount, --here causes the error
    };
  return qry.Where(r=>r.InvoiceAmount > r.PaidAmount ).ToListAsync();
}

执行上述代码时,我收到错误 System.InvalidOperationException:不支持对实体类型“PaymentStatus”进行比较,因为它是无密钥实体。

错误是由线路引起的

PaidAmount = pay==null ? 0 : pay.TotalPaidAmount 

如果改为

PaidAmount = pay.TotalPaidAmount 

然后它在 UnitTest(使用 InMemory 数据库)中工作,但在 SQL Server 中失败,因为翻译的 SQL 正在使用过滤记录

WHERE (inv.Amount > pay.PaidAmount)

当未支付发票时,PaymentStatuses 没有相应的发票记录,因此 pay.PaidAmount 为 Null(非零)。inv.Amount > Null 不满足。

我正在使用 EntityFrameworkCore 3.1.5

我不明白为什么

pay==null ? 0 : pay.TotalPaidAmount

抛出错误以及如何解决

标签: c#sql-serverasp.net-coreentity-framework-core

解决方案


我通过在 PaymentStatus 中使 TotalPaidAmount 为空来解决了这个问题

public class PaymentStatus
{
  public Guid InvoiceID {get;set;}
  public decimal? TotalPaidAmount {get;set;}
}

然后在getting Receivables中更改查询

public Task<List<Receivables>> GetReceivables()
{
  var qry = from inv in MyDbContext.Invoices
    from pay in MyDbContext.PaymentStatuses.Where(p => p.InvoiceID == inv.ID).DefaultIfEmpty()
    select new Receivables
    {
      InvoiceID = inv.ID,
      InvoiceAmount = inv.Amount,
      PaidAmount = pay.TotalPaidAmount ?? 0,
    };
  return qry.Where(r=>r.InvoiceAmount > r.PaidAmount ).ToListAsync();
}

推荐阅读