2012-09-07 11 views
16

Pracuję nad systemem wykorzystującym Entityframework i już od ponad 12 miesięcy, a projekt idzie dobrze, aż do wczoraj, kiedy mam teraz dziwny błąd, którego nie mam pojęcia. Pojawia się. robię nic innego, co mam zrobić wcześniej, ale raz załadować dany podmiot i próby uzyskania dostępu do jakichkolwiek podmiotów dziecko pojawia się następujący błąd:EntityFramework - Błąd proxy jednostki

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

Czy ktoś może rzucić jakieś światło na to, co to właściwie oznacza i co by to spowodowało?

Pokazanie mojego kodu naprawdę nie pomaga.

Tutaj jest uproszczoną wersją kodu:

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

Błąd występuje przy dostępie DeparturePoint i DestinationPoint ale Quote ładunki prawidłowo i wszystkie właściwości są ładowane.

Podmiot Cytat wygląda trochę tak:

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; } 
} 

Odpowiedz

32

Stało się to dla mnie zbyt kiedy starałem się wdrożyć ICloneable na mojej jednostki i sklonowano go za pomocą MemberwiseClone. Świetnie się spisałem, gdy używałem obiektów, które sam sobie wytworzyłem. Jednak gdy użyłem tego do sklonowania encji, która została załadowana przy użyciu EF, otrzymałem ten błąd za każdym razem, gdy próbowałem dodać go do DbSet (lub w różnych innych częściach).

Po pewnym kopaniu odkryłem, że podczas klonowania elementu ładowanego EF-em również klonujesz klasę proxy. Jedną z rzeczy, którą prowadzi klasa proxy, jest odniesienie do owinięcia danej jednostki. Ponieważ płytka kopia kopiuje jedynie odniesienie do opakowania, nagle masz dwie jednostki, które mają tę samą instancję opakowania.

W tym momencie EF myśli, że utworzyłeś lub pożyczyłeś inną klasę proxy dla twojej istoty, która, jak przypuszcza, jest przeznaczona dla złych intencji i blokuje ciebie.

Edit

Oto fragment, który stworzyłem w celu obejścia tego problemu. Zauważ, że będzie to sprawiedliwe zadanie kopiowania tylko właściwości EF, ale nie jest to doskonałe. Pamiętaj, że musisz go zmodyfikować, jeśli masz prywatne pola, które również muszą zostać skopiowane, ale masz pomysł.

/// <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; 

    } 
+1

Dzięki, miałem okropną metodę klonowania, a członek wydawał się magią, której potrzebowałem, wydaje się, że nie jest. Dzięki. – JamesStuddart

+0

MemberwiseClone często jest magią, której potrzebujesz, ale EF robi kilka wyjątkowych rzeczy. Przy okazji, jeśli uważasz, że to rozwiązanie nie jest wystarczające, słyszałem też o ludziach używających [AutoMappera] (http://automapper.org/) do taniego mechanizmu klonowania. Nie było to przeznaczone do tego celu, ale to nie znaczy, że nie jest to doskonałe rozwiązanie. –

+0

Dzięki, zrobiłem bzdurę za sprawą, ale kiedy dostanę czas, aby do niego wrócić, wdrożę jedno z podanych przez ciebie rozwiązań.Dzięki za twój wgląd, wydaje się, że w tej kwestii nie ma zbyt wielu rzeczy i mam nadzieję, że pomoże to także innym osobom. – JamesStuddart

1

Przede rozwiązania mogą wystąpić takie jak błędem „Sprzeczne zmiany roli x relacji y wykryto”. Osiągam ten błąd przy użyciu tej metody;

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

Mam nadzieję, że zadziała również dla Ciebie.

Powiązane problemy