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; -)
7 answers
Szukasz:
db.Users.Attach(updatedUser);
var entry = db.Entry(updatedUser);
entry.Property(e => e.Email).IsModified = true;
// other changed properties
db.SaveChanges();
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.
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();
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.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();
}
}
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ć..
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
-
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
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
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