Entity Framework 5 aktualizowanie rekordu

Badałem różne metody edycji / aktualizacji rekordu w ramach encji Framework 5 w ASP.NET środowiska MVC3, ale jak na razie żaden z nich nie zaznacza wszystkich pól, których potrzebuję. Wyjaśnię dlaczego.

Znalazłem trzy metody, do których wspomnę za i przeciw:

Metoda 1-załaduj oryginalny rekord, zaktualizuj każdą właściwość

var original = db.Users.Find(updatedUser.UserId);

if (original != null)
{
    original.BusinessEntityId = updatedUser.BusinessEntityId;
    original.Email = updatedUser.Email;
    original.EmployeeId = updatedUser.EmployeeId;
    original.Forename = updatedUser.Forename;
    original.Surname = updatedUser.Surname;
    original.Telephone = updatedUser.Telephone;
    original.Title = updatedUser.Title;
    original.Fax = updatedUser.Fax;
    original.ASPNetUserId = updatedUser.ASPNetUserId;
    db.SaveChanges();
}    

plusy

  • może określić, które właściwości zmieniają
  • widoki nie muszą zawierać wszystkich własność

Cons

  • 2 x zapytań do bazy danych, aby załadować oryginał, a następnie zaktualizować go

Metoda 2-Wczytaj oryginalny rekord, Ustaw zmienione wartości

var original = db.Users.Find(updatedUser.UserId);

if (original != null)
{
    db.Entry(original).CurrentValues.SetValues(updatedUser);
    db.SaveChanges();
}

plusy

  • tylko zmodyfikowane właściwości są wysyłane do bazy danych

Cons

  • widoki muszą zawierać każdą właściwość
  • 2 x zapytań do bazy danych, aby załadować oryginał, a następnie zaktualizować go

Metoda 3-Załącz zaktualizowany rekord i ustaw stan uprawniający.Modified

db.Users.Attach(updatedUser);
db.Entry(updatedUser).State = EntityState.Modified;
db.SaveChanges();

plusy

  • 1 x Zapytanie o bazę danych do aktualizacji

Cons

  • nie można określić, które właściwości zmieniają
  • widoki muszą zawierać każdą właściwość

Pytanie

Moje pytanie do was; czy jest czysty sposób, że mogę osiągnąć ten zestaw celów?

  • może określić, które właściwości zmieniają
  • Views don ' t need zawierać każdą właściwość(np. hasło!)
  • 1 x Zapytanie o bazę danych do aktualizacji

Rozumiem, że jest to dość drobna rzecz do zwrócenia uwagi, ale może brakuje mi prostego rozwiązania tego problemu. Jeśli nie metoda jedna zwycięży; -)

Author: Stokedout, 2013-03-11

7 answers

Szukasz:

db.Users.Attach(updatedUser);
var entry = db.Entry(updatedUser);
entry.Property(e => e.Email).IsModified = true;
// other changed properties
db.SaveChanges();
 650
Author: Ladislav Mrnka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-11 13:12:34

Bardzo podoba mi się przyjęta odpowiedź. Uważam, że istnieje jeszcze inny sposób podejścia do tej kwestii. Załóżmy, że masz bardzo krótką listę właściwości, których nigdy nie chciałbyś zawrzeć w widoku, więc podczas aktualizacji encji zostaną one pominięte. Załóżmy, że te dwa pola to hasło i SSN.

db.Users.Attach(updatedUser);

var entry = db.Entry(updatedUser);
entry.State = EntityState.Modified;

entry.Property(e => e.Password).IsModified = false;
entry.Property(e => e.SSN).IsModified = false;   

db.SaveChanges();   

Ten przykład pozwala zasadniczo zostawić logikę biznesową w spokoju po dodaniu nowego pola do tabeli użytkowników i widoku.

 169
Author: smd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-01 21:01:38
foreach(PropertyInfo propertyInfo in original.GetType().GetProperties()) {
    if (propertyInfo.GetValue(updatedUser, null) == null)
        propertyInfo.SetValue(updatedUser, propertyInfo.GetValue(original, null), null);
}
db.Entry(original).CurrentValues.SetValues(updatedUser);
db.SaveChanges();
 27
Author: Stefano Camisassi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-23 09:54:21

Dodałem dodatkową metodę aktualizacji do klasy bazowej repozytorium, która jest podobna do metody aktualizacji generowanej przez rusztowanie. Zamiast ustawiać cały obiekt na "zmodyfikowany", ustawia on zestaw poszczególnych właściwości. (T jest parametrem ogólnym klasy.)

public void Update(T obj, params Expression<Func<T, object>>[] propertiesToUpdate)
{
    Context.Set<T>().Attach(obj);

    foreach (var p in propertiesToUpdate)
    {
        Context.Entry(obj).Property(p).IsModified = true;
    }
}

A następnie wywołać, na przykład:

public void UpdatePasswordAndEmail(long userId, string password, string email)
{
    var user = new User {UserId = userId, Password = password, Email = email};

    Update(user, u => u.Password, u => u.Email);

    Save();
}
Lubię jedną wycieczkę do bazy danych. Prawdopodobnie lepiej jest to zrobić z modelami widoku, aby uniknąć powtarzania zestawów właściwości. Jeszcze tego nie zrobiłem, bo Nie wiem, jak uniknąć wprowadzania komunikatów walidacyjnych na moich weryfikatorach modelu widoku do mojego projektu domeny.
 21
Author: Ian Warburton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-13 21:31:07
public interface IRepository
{
    void Update<T>(T obj, params Expression<Func<T, object>>[] propertiesToUpdate) where T : class;
}

public class Repository : DbContext, IRepository
{
    public void Update<T>(T obj, params Expression<Func<T, object>>[] propertiesToUpdate) where T : class
    {
        Set<T>().Attach(obj);
        propertiesToUpdate.ToList().ForEach(p => Entry(obj).Property(p).IsModified = true);
        SaveChanges();
    }
}
 8
Author: Matthew Steven Monkan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-16 16:04:01

Wystarczy dodać do listy opcji. Możesz również pobrać obiekt z bazy danych i użyć narzędzia automatycznego mapowania, takiego jak Auto Mapper, aby zaktualizować części rekordu, które chcesz zmienić..

 2
Author: Bostwick,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-03 15:58:36

W zależności od przypadku zastosowania, wszystkie powyższe rozwiązania mają zastosowanie. Tak zwykle jednak to robię:

Dla kodu po stronie serwera (np. procesu wsadowego) zazwyczaj Ładuję encje i pracuję z dynamicznymi proxy. Zazwyczaj w procesach wsadowych musisz załadować dane w czasie uruchamiania usługi. Staram się wsadowo załadować dane zamiast używać metody find, aby zaoszczędzić trochę czasu. W zależności od procesu używam optymistycznej lub pesymistycznej kontroli współbieżności (zawsze używam optymistycznej z wyjątkiem w przypadku scenariuszy wykonywania równoległego, gdzie muszę zablokować niektóre rekordy za pomocą prostych poleceń sql, jest to jednak rzadkie). W zależności od kodu i scenariusza wpływ można zredukować do niemal zera.

Dla scenariuszy po stronie klienta, masz kilka opcji

  1. Użyj modeli widoku. Modele powinny mieć właściwość UpdateStatus (unmodified-inserted-updated-deleted). Obowiązkiem klienta jest ustawienie poprawnej wartości tej kolumny w zależności od działań użytkownika (insert-update-delete). Serwer może albo zapytać db o oryginalne wartości lub klient powinien wysłać oryginalne wartości do serwera wraz ze zmienionymi wierszami. Serwer powinien dołączyć oryginalne wartości i użyć kolumny UpdateStatus dla każdego wiersza, aby zdecydować, jak obsłużyć nowe wartości. W tym scenariuszu zawsze używam optymistycznej współbieżności. Spowoduje to tylko instrukcje insert-update-delete, a nie select, ale może potrzebować sprytnego kodu, aby przejść przez wykres i zaktualizować podmioty (w zależności od scenariusza-aplikacja). Maper może pomóc, ale nie obsługuje logiki CRUD

  2. Użyj biblioteki jak bryza.js, który ukrywa większość tej złożoności (jak opisano w 1) i spróbuj dopasować go do swojego przypadku użycia.

Hope it helps

 1
Author: Chriss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-30 12:07:46