Ответ 1
Это случилось и со мной, когда я попытался реализовать ICloneable на моем объекте и клонировал его, используя MemberwiseClone. Работал отлично, когда я использовал объекты, которые я создал сам. Однако, когда я использовал это для клонирования объекта, который был загружен с использованием EF, я получил эту ошибку всякий раз, когда я пытался добавить ее в DbSet (или в другие другие части).
После некоторого копания я обнаружил, что когда вы клонируете объект, загруженный EF, вы клонируете и прокси-класс. Одна из вещей, которые несет прокси-класс, - это ссылка на оболочку для данного объекта. Поскольку мелкая копия копирует только ссылку на оболочку, у вас вдруг есть два объекта, которые имеют один и тот же экземпляр обертки.
В этот момент EF думает, что вы создали или заимствовали другой прокси-класс для своей сущности, который он предполагает, для целей нанесения вреда и блокирует вас.
Edit
Вот фрагмент, который я создал для решения этой проблемы. Обратите внимание, что это сделает справедливую работу по копированию только свойств EF, но это не идеально. Обратите внимание, что вам нужно будет изменить его, если у вас есть частные поля, которые также должны быть скопированы, но вы получите эту идею.
/// <summary>
/// Makes a shallow copy of an entity object. This works much like a MemberwiseClone
/// but directly instantiates a new object and copies only properties that work with
/// EF and don't have the NotMappedAttribute.
/// </summary>
/// <typeparam name="TEntity">The entity type.</typeparam>
/// <param name="source">The source entity.</param>
public static TEntity ShallowCopyEntity<TEntity>(TEntity source) where TEntity : class, new()
{
// Get properties from EF that are read/write and not marked witht he NotMappedAttribute
var sourceProperties = typeof(TEntity)
.GetProperties()
.Where(p => p.CanRead && p.CanWrite &&
p.GetCustomAttributes(typeof(System.ComponentModel.DataAnnotations.NotMappedAttribute), true).Length == 0);
var newObj = new TEntity();
foreach (var property in sourceProperties)
{
// Copy value
property.SetValue(newObj, property.GetValue(source, null), null);
}
return newObj;
}