【发布时间】:2022-12-01 16:53:48
【问题描述】:
假设有一个模型有条目。每个条目都有一种货币。我想像这样更新货币:
var model = await _dbContext.Models
.Include(x => x.Entries)
.FirstOrDefaultAsync(x => x.Id.ToString().Equals(command.Id), cancellationToken);
model.Name = command.Name;
command.Entries.ForEach(x =>
{
var entry = _dbContext.Entries
.Find(Guid.Parse(x.Id));
var currency = _dbContext.Currencies
.FirstOrDefault(y => y.Id.Equals(x.CurrencyId));
entry.Currency = currency;
});
await _dbContext.SaveChangesAsync(cancellationToken);
以下是货币关系的定义方式:
modelBuilder.Entity<Entry>()
.HasOne<Currency>(x => x.Currency)
.WithMany();
我正在调试可以为货币分配一个值但不能为空的问题。例如。
command.Entries.ForEach(x =>
{
var entry = _dbContext.Entries
.Find(Guid.Parse(x.Id));
entry.Currency = null;
});
不会将货币设置为 null 但这有效:
command.Entries.ForEach(x =>
{
var entry = _dbContext.Entries
.Find(Guid.Parse(x.Id));
var currency = ...
entry.Currency = currency;
});
货币已正确更新。现在,当我在 ForEach 之外进行更新时,它会起作用:
var entry = _dbContext.Entries.Find(Guid.Parse(".."));
entry.Currency = null;
await _dbContext.SaveChangesAsync(cancellationToken);
所以 ForEach 似乎是问题所在。任何想法为什么?奇怪的是,货币可以更新为一个值,但不能在 ForEach 内部设置为 null。
【问题讨论】:
-
旁注:这是一种非常低效的更新条目的方法。您通过数据库中的单个查询获取每个条目。最好一次全部取回。货币也一样。
-
ForEach不是 LINQ 命令,也没有转换为 SQL。这是一个 List<T> 方法,除了foreach(var item in thatList)会做的但lambda 是一个单独的范围。entry在 lambda 之外不存在 -
代码是非常慢,因为它一个一个地加载实体。您可以将
ForEach替换为_dbContext.Entries.Where(e=>listOfIds.Contains(e.Id))以生成ID in (@id1, @id2, @id3,....)子句。如果您使用Inlude(e=>e.Currency),则无需单独加载Currency。即使是现在,您也可以显式加载它