【发布时间】:2017-06-09 21:47:18
【问题描述】:
每次我想更新我的记录时,我都会收到以下错误:
“无法跟踪实体类型‘用户’的实例,因为另一个 已在跟踪具有相同密钥的此类实例。什么时候 添加新实体,对于大多数键类型,一个唯一的临时键值 如果没有设置键(即,如果键属性已分配)将被创建 其类型的默认值)。如果您明确设置密钥 新实体的值,确保它们不会与现有实体发生冲突 为其他新实体生成的实体或临时值。什么时候 附加现有实体,确保只有一个实体实例具有 给定的键值附加到上下文。"
这是我的代码:
public void SaveRecipient(Recipient myRecipient)
{
if (myRecipient.RecipientGUID == Guid.Empty)
{
myRecipient.RecipientGUID = Guid.NewGuid();
foreach (ContactMethod tmpCM in myRecipient.ContactMethods)
{
context.Entry(tmpCM.Type).State = EntityState.Unchanged;
}
context.Entry(myRecipient.LastModifiedBy).State = EntityState.Unchanged;
context.Entry(myRecipient.Owner).State = EntityState.Unchanged;
context.Entry(myRecipient.CreatedBy).State = EntityState.Unchanged;
context.Recipients.Add(myRecipient);
}
else
{
var dbRecipient = context.Recipients
.Include(a => a.ContactMethods).ThenInclude(t => t.Type)
.Include(b => b.CreatedBy)
.Include(c => c.LastModifiedBy)
.Include(d => d.Owner).ThenInclude(o => o.Users)
.FirstOrDefault(x => x.RecipientGUID == myRecipient.RecipientGUID);
if (dbRecipient != null)
{
dbRecipient.FirstName = myRecipient.FirstName;
dbRecipient.LastName = myRecipient.LastName;
dbRecipient.Company = myRecipient.Company;
foreach (ContactMethod tmpCM in myRecipient.ContactMethods)
{
var dbCM = dbRecipient.ContactMethods.FirstOrDefault(x => x.ContactMethodGUID == tmpCM.ContactMethodGUID);
if (dbCM != null)
{
dbCM.CountryCode = tmpCM.CountryCode;
dbCM.Identifier = tmpCM.Identifier;
dbCM.IsPreferred = tmpCM.IsPreferred;
}
else
{
dbRecipient.ContactMethods.Add(tmpCM);
}
}
//Only update this if it has changed.
if (dbRecipient.LastModifiedBy.UserGUID != myRecipient.LastModifiedBy.UserGUID)
{
dbRecipient.LastModifiedBy = myRecipient.LastModifiedBy;
}
dbRecipient.LastModifiedOn = myRecipient.LastModifiedOn;
}
}
context.SaveChanges();
}
相关类:
用户:
public class User
{
[Key]
public Guid UserGUID { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public bool IsSiteAdmin { get; set; }
public bool IsActive { get; set; }
public DateTime? CreatedOn { get; set; }
public DateTime? LastLogin { get; set; }
}
收件人:
public class Recipient
{
[Key]
public Guid RecipientGUID { get; set; }
[Required(ErrorMessage = "Please enter a Recipient's First Name.")]
public string FirstName { get; set; }
[Required(ErrorMessage = "Please enter a Recipient's Last Name.")]
public string LastName { get; set; }
public string Company { get; set; }
public UserGroup Owner { get; set; }
public virtual ICollection<ContactMethod> ContactMethods { get; set; }
public User CreatedBy { get; set; }
public DateTime CreatedOn { get; set; }
public User LastModifiedBy { get; set; }
public DateTime LastModifiedOn { get; set; }
public bool IsActive { get; set; }
}
联系方式:
public class ContactMethod
{
[Key]
[HiddenInput(DisplayValue = false)]
public Guid ContactMethodGUID { get; set; }
[ForeignKey("ContactMethodTypeGUID")]
public virtual ContactMethodType Type { get; set; }
public string CountryCode { get; set; }
[Required]
public string Identifier { get; set; }
public bool IsPreferred { get; set; }
[ForeignKey("RecipientGUID")]
public virtual Recipient Owner { get; set; }
}
当我想更新收件人并且是另一个用户进行更新时,会发生此问题。所以说用户 abcd 做了最后一次更新,但现在用户 zyx 更新了记录。因此 Recipeint.LastUpdatedBy 设置为当前会话用户。当我这样做时,我得到了上述错误。我无法弄清楚如何超越这一点。
一个小提示:如果我添加这个:
context.Entry(myRecipient.LastModifiedBy).State = EntityState.Unchanged;
在if (dbRecipient.LastModifiedBy.UserGUID != myRecipient.LastModifiedBy.UserGUID)
语句,并说用户 lastmodifiedby 设置为用户 abc。现在user asfg第一次更新这个receiver,就通过了,LastModifiedBy会设置成user asfg,但是说user abc回去又改了receiver,所以lastmodifiedby又回到abc,失败了,同样的错误.
这让我发疯了,我想不通!!!
【问题讨论】:
-
你在使用依赖注入吗?可能是您使用了定义
SaveRecipient的类作为单例?它应该是Scoped,这样你就有了每个请求的上下文。 -
是的,我是。谢谢,我去看看。
-
所以我的收件人类包含两个用户字段。一个用于 CreatedBy,另一个用于 LastModifiedBy。因此,当这些设置为同一用户时,我会收到此错误。我不认为我的模型有什么问题,我的意思是这样组织它是有意义的。
标签: c# entity-framework asp.net-core-mvc .net-core entity-framework-core