c# - 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
抛出错误以及如何解决
解决方案
我通过在 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();
}
推荐阅读
- mongodb - 查找每个学科的前 3 名学生 MongoDB
- nginx - ngnix 上的目录列表
- heroku - Heroku ps:exec 更改在服务器重新启动后重置
- python - msvcrt.getch() 没有响应杀死它的线程
- java - 没有 IO 流就不存在 NIO 通道?
- java - Android Studio 4.1.1 资源链接失败
- laravel - 尝试获取非对象的属性“android_id”时出错
- python - ValueError:尝试使用不受支持的类型转换值(无)(
) 到张量 - typo3 - TYPO3 TCA 内联向导
- discord.py - Discord.py status 不显示会员在线状态,而是显示离线