2012-07-02 19 views
7

Korzystanie z asp.net 4 chociaż C#.LINQ do SQL - aktualizacja rekordów

W mojej warstwie dostępu do danych mam metody do zapisywania i aktualizowania rekordów. Zapisywanie jest łatwe, ale aktualizacja jest uciążliwa.

Poprzednio użyłem SubSonic, który był świetny, ponieważ miał aktywny rekord i wiedział, że jeśli załadowałem rekord, zmieniłem kilka wpisów, a następnie zapisałem je ponownie, to rozpoznało to jako aktualizację i nie próbowało zapisać nowego wpis w DB.

Nie wiem, jak zrobić to samo w LINQ. W rezultacie mój workflow jest tak:

  1. web page chwyta „nagrać” z DB
  2. Niektóre wartości w nim są zmieniane przez użytkownika.
  3. "Rekord A" jest przesyłany z powrotem do warstwy dostępu do danych
  4. Teraz muszę ponownie załadować Rekord A, nazywając go "ZapisaneRekord A", zaktualizować wszystkie wartości w tym obiekcie wartościami z podanego "Rekordu A" a następnie zaktualizuj/zapisz "SavedRecord A"!

Jeśli po prostu zapiszę "Record A", otrzymam nowy wpis w DB.

Oczywiście byłoby ładniejsze po prostu przejść nagrać i zrobić coś takiego:

RecordA.Update(); 

Ja zakładając, że coś mi tu brakuje, ale nie mogę znaleźć prostą odpowiedź on-line.

Odpowiedz

1

Kiedy LINQ-SQL aktualizuje rekord w bazie danych, musi dokładnie wiedzieć, jakie zmieniono pola, aby je tylko zaktualizować. W zasadzie są trzy opcje:

  • Gdy zaktualizowane dane wysłane z powrotem do serwera, należy załadować istniejące dane z bazy danych, należy przypisać wszystkie właściwości załadowanego obiektu i nazywają SubmitChanges(). Wszelkie właściwości, które mają przypisaną istniejącą wartość, nie zostaną zaktualizowane.
  • Śledź niezmodyfikowany stan obiektu i użyj Attach z niezmodyfikowanymi i zmodyfikowanymi wartościami.
  • Zainicjuj nowy obiekt ze wszystkimi stanami wymaganymi przez optymistyczną kontrolę współbieżności (jeśli jest włączona, która jest domyślnie).Następnie dołącz obiekt i na koniec zaktualizuj wszystkie zmienione właściwości po dołączeniu, aby zmienić śledzący zmiany danych DataContext zaktualizowany.

Zwykle używam pierwszej opcji, ponieważ jest najłatwiejsza. Występuje kara za wykonanie z dwoma wywołaniami DB, ale jeśli nie robisz wielu aktualizacji, nie będzie to miało znaczenia.

+0

Dzięki, to zaskakujące, że nie ma lepszego sposobu na zrobienie tego. Robiłem metodę "dwóch wywołań DB", odkąd zaczynałem używać LINQ do SQL, ale zawsze miałem dokuczliwe uczucie, że brakowało mi oczywiście łatwiejszej odpowiedzi. Wygląda na to, że nie mam, co jest dobre i złe. –

2

można osiągnąć, co chcesz za pomocą Attach method na przykład Table i popełnienie metodą SubmitChanges() na DataContext.

Proces ten może nie być tak prosty, jak byśmy sobie życzyli, ale można przeczytać artykuł Davida DeWintera o numerze LINQ to SQL: Updating Entities, aby uzyskać bardziej szczegółowe wyjaśnienie/samouczek.

+0

Dzięki, sprawdzi to. –

1

Załóżmy, że masz klasę produktów OR DB, to musisz to zrobić.

DbContext _db = new DbContext(); 

    var _product = (from p in _db.Products 
            where p.Id == 1 // suppose you getting the first product 
            select p).First(); // this will fetch the first record. 

    _product.ProductName = "New Product"; 

    _db.SaveChanges(); 

     // this is for EF LINQ to Objects 
    _db.Entry(_product).State = EntityState.Modified; 
    _db.SaveChanges(); 

------------------------------------------------------------------------------------- 
this is another example using Attach 
------------------------------------------------------------------------------------- 

public static void Update(IEnumerable<Sample> samples , DataClassesDataContext db) 
{ 
    db.Samples.AttachAll(samples); 
    db.Refresh(RefreshMode.KeepCurrentValues, samples) 
    db.SubmitChanges(); 
} 

przypadku podłączenia jednostki do kontekstu, a następnie odśwież (z KeepCurrentValues ​​zaznaczona), LINQ to SQL dostanie te podmioty z serwera, porównać je i zaznacz zaktualizowane tych, które są różne

+0

Dzięki, w moim przypadku, chociaż tak naprawdę nie wiem, które pola zostały zmienione, ponieważ użytkownik będzie robił montaż. W związku z tym muszę założyć, że wszystkie pola uległy zmianie i odpowiednio zapisać aktualizację. To żmudne, ale przynajmniej wiem, że robiłem to w sposób "właściwy", nawet jeśli nie wydaje się, że tak jest. –

+0

Nie ma znaczenia jakie pola zostały edytowane przez użytkownika, o ile przekazujesz model do ActionResult w kontrolerze w metodzie HTTPPOST i wywołuje SaveChanges(), całe rekordy są aktualizowane w DB. –

+0

Czy możliwe jest wykonanie tej pracy tam, gdzie klient przekazał tylko jedną zmienioną wartość + kluczowe pole odniesienia? Powiedzmy, że przekazujesz im zserializowany rekord i odsyłają zaktualizowany zserializowany rekord zawierający tylko te dwa pola. Do tej pory w moich testach LinqToSql po prostu próbował nadpisać istniejące dane wartościami null. Oczywiście oznacza to, że nigdy nie będziesz w stanie jawnie zerować pola zerowego. Staram się unikać pisania dużo tego pola = pola. – RoboJ1M