EntityFramework - ошибка прокси-сервера Entity - программирование

EntityFramework - ошибка прокси-сервера Entity

Я работаю над системой, использующей Entityframework и уже более 12 месяцев, и проект идет хорошо, вплоть до вчерашнего дня, когда у меня появилась странная ошибка, о которой я не знаю, почему это происходит. Я ничего не делаю по сравнению с тем, что я делал раньше, но как только я загружу объект, о котором идет речь, и попытаюсь получить доступ к любым дочерним объектам, я получаю следующую ошибку:

The entity wrapper stored in the proxy does not reference the same proxy

Может ли кто-нибудь пролить свет на то, что это на самом деле означает и что может вызвать это?

Показать мой код действительно не помогает.

Вот упрощенная версия кода:

var quote = new QuoteHelper().GetById(orderId);
var updatedQuotes = new Provider().GetExportQuotes(quote.DeparturePoint.Id,quote.DestinationPoint);

Ошибка при доступе к параметрам DeparturePoint и DestinationPoint, но Quote загружается правильно, и все свойства загружаются.

Сущность Quote выглядит примерно так:

public class Quote : BaseQuote, ICloneable
{
     public Guid DeparturePointId { get; set; }
     public virtual LocationPoint DeparturePoint{ get; set; }

     public Guid DestinationPointId { get; set; }
     public virtual LocationPoint DestinationPoint{ get; set; }
}
4b9b3361

Ответ 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;

    }

Ответ 2

Возможно, возникло такое решение, как ошибка " Были обнаружены конфликтующие изменения в роли x отношения y". Я получаю эту ошибку при использовании этого метода;

 public virtual TEntity DetachEntity(TEntity entityToDetach)
    {
        if (entityToDetach != null)
            context.Entry(entityToDetach).State = EntityState.Detached;
        context.SaveChanges();
        return entityToDetach;
    }

Я надеюсь, что это сработает и для вас.

Ответ 3

Я решил это таким образом.

using (var ctx = new MyContext())
      {
         ctx.Configuration.ProxyCreationEnabled = false;

         return ctx.Deferrals.AsNoTracking().Where(r => 
         r.DeferralID.Equals(deferralID)).FirstOrDefault();
      }