我正在尝试建立一个在使用自跟踪实体和实体框架4时使用辅助键的良好实践,但似乎有很多陷阱。
假设我有一个报警实体,它可以对用户具有ConfirmingUser导航属性。用户的主键是Id,次键是“Login”。
在我的系统中的某个时候,我将一个新的用户实体分配给报警确认器。在这一点上,我只知道用户的登录名(secondary key),假设这是一个n层架构,在那里查找Id是不切实际的。
警报随后被传输到将尝试存储警报的持久层。
现在是棘手的部分。我需要确定确认器是否已经存在于数据库中,并采取适当的措施。
我现在就是这样做的:
using (var context = new PantoTestEntities())
{
if (alarm.ConfirmingUser != null && alarm.ConfirmingUser.ChangeTracker.State == ObjectState.Added)
{
var userIdQuery = from user in context.Users
where user.Login == alarm.ConfirmingUser.Login
select user.Id;
if (userIdQuery.Any())
{
// Disable cache or ApplyChanges will throw an exception, because the user already exists.
context.Alarms.MergeOption = MergeOption.NoTracking;
alarm.ConfirmingUser.Id = userIdQuery.First();
alarm.ConfirmingUser.MarkAsModified();
}
}
context.Alarms.ApplyChanges(alarm);
context.SaveChanges();
// Accept changes in the full entity graph
alarm.AcceptAllChanges();
}
在我看来,这种模式既丑陋又低效。有没有更好的方法来处理带有“外部”键的实体?
原因是自跟踪实体的ApplyChanges会尝试将原始用户和新用户复制到EF上下文中,但是EF不允许原始值和新值都是同一个实体(为什么它不能处理这一点我不清楚)。