レコードを更新するたびに、次のエラーが表示されます。
"エンティティタイプ 'User'のインスタンスは、同じキーを持つこのタイプの別のインスタンスがすでに追跡されているため追跡できません。新しいエンティティを追加するとき、ほとんどのキータイプに対して、キーが設定されていないと、つまり、キープロパティにそのタイプのデフォルト値が割り当てられている場合)新しいエンティティのキー値を明示的に設定する場合は、既存のエンティティまたは他の新しいエンティティに対して生成された一時的な値と衝突しないようにします。特定のキー値を持つエンティティインスタンスが1つだけコンテキストに関連付けられます。
ここに私のコードです:
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に設定されているとします。ユーザーが最初にこの受信者を更新すると、それが通過し、LastModifiedByがユーザーasfgに設定されますが、ユーザーabcが元に戻って受信者を再度変更すると、lastmodifiedbyはabcに戻ります。 。
これは私にナッツを運転していると私はそれを把握することはできません!
私はMicrosoftの Arthur Vickersからこれに対する答えを得ました。私は共有したいと思った。
ナビゲーションプロパティdbRecipient.LastModifiedBy
を設定するコードは、コンテキストによってトラッキングされていないエンティティインスタンスに設定しています。この場合、コンテキストは既にこの同じエンティティの別のインスタンスを追跡しているようです。おそらく、 CreatedBy
ナビゲーションを含めてクエリによってCreatedBy
ためです。
EFは同じエンティティの2つのインスタンスをトラッキングできないため、例外がスローされるため、ここでEFに何をすべきかを知るために追加情報を与える必要があります。これは、一般的な場合には複雑になる可能性がある。
たとえば、追跡されたインスタンスのプロパティが他のインスタンスで変更されている場合などです。
しかし、そうでないと仮定すると、追跡されているインスタンスを検索し、代わりに使用することができます(例:
if (dbRecipient.LastModifiedBy.UserGUID != myRecipient.LastModifiedBy.UserGUID)
{
dbRecipient.LastModifiedBy = test.Set<User>().Find(myRecipient.LastModifiedBy.UserGUID);
}