2016-04-15 40 views
7

Pracuję nad aplikacją sieci Web C# ASP.NET MVC 5 z EF 5. Mapowanie moich tabel bazy danych za pomocą EF generuje klasę DbContext i plik .edmx. Dzisiaj czytałem a great article about creating generic DAL classes, ale zatrzymał się na następnym zdaniu:Mylące artykuły i dokumentacja o różnicach (jeśli występują) między System.Data.EntityState.Add i DbSet.Add

Należy pamiętać, że stosując metodę wprowadzania do zmiany stanu podmiotu będzie wpływa tylko rzeczywisty podmiot, które przechodzą w metody. Nie będzie ona kolidować z wykresem i ustawiać stanu wszystkich powiązanych obiektów, w przeciwieństwie do metody DbSet.Add.

To zaprzecza temu, co jest wymienione w tych pytaniach:

W odpowiedzi na wszystkie powyższe pytania wszyscy użytkownicy wspomnieli, że używanie System.Data.EntityState.Added jest dokładnie takie samo jak przy użyciu DbSet.Add. Ale pierwszy artykuł, o którym wspomniałem, mówi, że używanie System.Data.EntityState.Added nie będzie kaskadować wykresu.

Na podstawie mojego testu stwierdzam, że użycie System.Data.EntityState.Added spowoduje kaskadę wykresu, tak jak w przypadku DBset.Add. Czy artykuł jest błędny, czy jest to mój test i Q & A?

Odpowiedz

5

Metody te są takie same, które można zweryfikować poprzez regularne testowanie lub, jeśli chcesz być całkowicie pewny, przez pewne eksploracje kodu EF 6.

  1. DbSet.Add metoda (http://entityframework.codeplex.com/SourceControl/latest#src/EntityFramework/DbSet.cs)

    public virtual TEntity Add(TEntity entity) 
    { 
        Check.NotNull<TEntity>(entity, "entity"); 
        this.GetInternalSetWithCheck("Add").Add((object) entity); 
        return entity; 
    } 
    

Wymaga InternalSet<T>.Add(object) metody.

  1. DbEntityEntry<T>.State właściwość (http://entityframework.codeplex.com/SourceControl/latest#src/EntityFramework/Infrastructure/DbEntityEntry.cs)

    public EntityState State 
    { 
        get { return _internalEntityEntry.State; } 
        set { _internalEntityEntry.State = value; } 
    } 
    

przypadku _internalEntityEntry jest InternalEntityEntry typu.

InternalEntityEntry.State nieruchomość (http://entityframework.codeplex.com/SourceControl/latest#src/EntityFramework/Internal/EntityEntries/InternalEntityEntry.cs)

public virtual EntityState State 
    { 
     get { return IsDetached ? EntityState.Detached : _stateEntry.State; } 
     set 
     { 
      if (!IsDetached) 
      { 
       if (_stateEntry.State == EntityState.Modified 
        && value == EntityState.Unchanged) 
       { 
        // Special case modified to unchanged to be "reject changes" even 
        // ChangeState will do "accept changes". This keeps the behavior consistent with 
        // setting modified to false at the property level (once that is supported). 
        CurrentValues.SetValues(OriginalValues); 
       } 
       _stateEntry.ChangeState(value); 
      } 
      else 
      { 
       switch (value) 
       { 
        case EntityState.Added: 
         _internalContext.Set(_entityType).InternalSet.Add(_entity); 
         break; 
        case EntityState.Unchanged: 
         _internalContext.Set(_entityType).InternalSet.Attach(_entity); 
         break; 
        case EntityState.Modified: 
        case EntityState.Deleted: 
         _internalContext.Set(_entityType).InternalSet.Attach(_entity); 
         _stateEntry = _internalContext.GetStateEntry(_entity); 
         Debug.Assert(_stateEntry != null, "_stateEntry should not be null after Attach."); 
         _stateEntry.ChangeState(value); 
         break; 
       } 
      } 
     } 
    } 

Widać, że jeżeli jednostka jest odłączona (sprawa) i stan dodaje - to samo InternalSet<T>.Add(object) nazywa.

Co do weryfikacji za pomocą badań:

using (var ctx = new TestDBEntities()) { 
    // just some entity, details does not matter 
    var code = new Code(); 
    // another entity 
    var error = new Error(); 
    // Code has a collection of Errors 
    code.Errors.Add(error); 
    var codeEntry = ctx.Entry(code); 
    // modify code entry and mark as added 
    codeEntry.State = EntityState.Added; 
    // note we did not do anything with Error 
    var errorEntry = ctx.Entry(error); 
    // but it is marked as Added too, because when marking Code as Added - 
    // navigation properties were also explored and attached, just like when 
    // you do DbSet.Add 
    Debug.Assert(errorEntry.State == EntityState.Added);     
} 
+0

więc mówisz, że za pomocą EntityState.Added i przy użyciu DBset.Add są dokładnie takie same? –

+1

Tak, jeśli twoja encja nie jest śledzona przez kontekst, obie metody będą robić dokładnie to samo, z dokładnie takim samym wynikiem, co jest potwierdzone przez przykład testowy i eksplorację kodu źródłowego. – Evk

+0

więc powiedzmy, że obiekt jest śledzony przez kontekst, to czy będą się różnić? jak powiedziałeś "jeśli twoja jednostka nie jest śledzona ..." –

5

nie wiem, autor tego bloga. Znam pisarzy z book DbContext choć (choć nie osobiście). Znają EF na wylot. Tak więc, gdy na stronie 80 piszą

Wywołanie DbSet.Add i ustawienie State do Added zarówno osiągnąć dokładnie to samo.

Wiem, co robię. Robią dokładnie to samo, co jest:

Jeśli jednostka nie jest śledzona przez kontekst, to zaczną być śledzone przez kontekst w paƒstwa Added. Zarówno DbSet.Add i ustawienie State do Added są operacjami graficznymi - oznacza to, że wszelkie inne jednostki, które nie są śledzone przez kontekst i są osiągalne z jednostki głównej, będą również oznaczone jako Added.

Z doświadczenia wiem też, że działa w ten sposób. Ale, aby usunąć wszelkie wątpliwości, w kodzie źródłowym EF, zarówno DbSet.Add i DbEntityEntry.State (przy ustawieniu Added) przybyć w tym samym punkcie w ObjectContext który ma rzeczywistej pracy:

public virtual void AddObject(string entitySetName, object entity) 

Jest to cecha, która nadal łudzić deweloperom że zacznij pracować z EF, jak wynika z dużej liczby pytań w StackOverflow, pytających o coś w stylu "dlaczego moje jednostki są duplikowane?". Julie Lerman napisała entire blog wyjaśniając, dlaczego tak się może stać.

To ciągłe złudzenie spowodowało, że zespół EF zdecydował się na change this behavior w EF7.

Może pisarz bloga, do którego się odnosiłeś, był jednym z tych złudnych deweloperów.