【发布时间】:2021-03-05 11:21:15
【问题描述】:
我已经一直在努力让它发挥作用,但没有成功。
架构: WPF 应用程序在 Azure WebApp(带有 JWT 的 ASP.NET Core ReST API)上添加、更新、接收和删除实体。
问题
当我第一次添加一个“事件”实体时,它确实工作得很好。即使是“第一轮”的更新也可以无缝工作。但是,如果我关闭 WPF 应用程序并尝试更新,它不起作用并抛出异常,无论我尝试在代码中修改什么都不起作用。
无法跟踪“事件”类型的实体,因为备用键属性“UniqueId”为空。如果备用键未在关系中使用,则考虑改用唯一索引。唯一索引可能包含空值,而备用键可能不包含。
UniqueId 不是 ID,它将用作可能会或可能不会出现的报告的外键。但可以肯定并确认,UniqueId 永远不会为空。我不知道为什么它一直告诉我。
有什么想法吗?
事件
internal class IncidentConfiguration : IEntityTypeConfiguration<Incident>
{
internal static IncidentConfiguration Create() => new();
public void Configure(EntityTypeBuilder<Incident> builder)
{
builder
.Property(incident => incident.Id)
.ValueGeneratedOnAdd();
builder
.Property(incident => incident.RowVersion)
.IsConcurrencyToken()
.ValueGeneratedOnAddOrUpdate();
builder
.Property(incident => incident.UniqueId)
.HasField("_uniqueId")
.IsRequired();
builder
.Property(incident => incident.Completion)
.HasField("_completion");
builder
.Property(incident => incident.Status)
.HasField("_status");
builder
.Property(incident => incident.Estimated)
.HasField("_estimated")
.HasConversion(new TimeSpanToTicksConverter());
builder
.Property(incident => incident.Actual)
.HasField("_actual")
.HasConversion(new TimeSpanToTicksConverter());
builder
.Property(incident => incident.Closed)
.HasField("_closed");
builder
.Property(incident => incident.Comments)
.HasField("_comments");
builder
.Property(incident => incident.Opened)
.HasField("_opened");
builder
.Property(incident => incident.Updated)
.HasField("_updated");
builder
.Property(incident => incident.BriefDescripion)
.HasField("_briefDescripion");
builder
.Property(incident => incident.Project)
.HasField("_project");
builder
.Ignore(incident => incident.IsUpdated);
}
}
举报
internal class ReportConfiguration : IEntityTypeConfiguration<Report>
{
internal static ReportConfiguration Create() => new();
public void Configure(EntityTypeBuilder<Report> builder)
{
builder
.Property(report => report.Id)
.ValueGeneratedOnAdd();
builder
.Property(report => report.RowVersion)
.IsConcurrencyToken()
.ValueGeneratedOnAddOrUpdate();
builder
.HasOne(report => report.Incident)
.WithMany(incident => incident.Reports)
.HasForeignKey(report => report.UniqueId)
.HasPrincipalKey(incident => incident.UniqueId)
.OnDelete(DeleteBehavior.Cascade);
builder
.Ignore(report => report.IsUpdated);
}
}
“更新”方法
public async Task<bool> UpdateAsync(Common.Models.Incident incident)
{
_manualResetEvent.WaitOne();
try
{
using var context = new IncidentManagerContext(_connectionString);
context.Incidents.Update(incident);
bool saveFailed;
do
{
saveFailed = false;
try
{
await context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException ex)
{
saveFailed = true;
var entry = ex.Entries.Single();
entry.OriginalValues.SetValues(entry.GetDatabaseValues());
}
} while (saveFailed);
}
catch (Exception) { return false; }
finally { _manualResetEvent.Set(); }
return true;
}
【问题讨论】:
-
又钓鱼了一天,我怀疑这可能是一些基于命名约定的行为。甚至“.ValueGeneratedNever()”标记也无济于事。也许 EF 核心以不同的方式处理名称以“Id”结尾的实体(属性)。似乎 EF Core 只是简单地忽略了提供的字符串值并尝试先设置 null。
-
另一个观察:在摆脱了那个糟糕的错误之后,又出现了另一个奇怪的行为。在几轮“更新”之后,“context.Incidents.Update(incident)”开始添加空实体而不是更新。这可能是最初的“空”错误的原因。那么,为什么 EF Core 会出人意料地添加“Null”条目而不是更新应该更新的内容呢?
-
实际上,Entity Framwork 已经没有多少耐心了,我即将将所有内容重构回传统的数据库访问方法......
-
EF 的自动魔法行为确实令人沮丧。麻烦多于其价值。
标签: c# asp.net-core entity-framework-core