2016-11-30 27 views
14

Mam kod Entity Framework 6 Pierwszy model wygenerowany z istniejącej bazy danych SQL Server. Baza danych używa śledzenia zmian SQL Server, więc dla wszystkich operacji manipulacji danymi generowanych z EF, chcę ustawić kontekst zmiany śledzenia w celu odróżnienia ich od zmian dokonanych przez inne procesy zewnętrzne. Odbywa się to zazwyczaj w T-SQL jako
WITH CHANGE_TRACKING_CONTEXT (@source_id) UPDATE <table>...Obsługa śledzenia zmian w serwerze SQL za pomocą Entity Framework 6

Jedyne co myślę, jest dołączana powyższej klauzuli SQL SQL generowany przez EF. Chociaż wydaje się, że modyfikowanie SQL wygenerowanego przez ORM jest wątpliwe. Mimo to, nawet jeśli chcę, nie wiem, gdzie można to zrobić. Czy możliwe jest przechwycenie EF Command Interception?

Pytanie dotyczy konkretnie zastosowania funkcji śledzenia zmian programu SQL Server w połączeniu z EF (a nie śledzeniem zmian EF). Pod względem EF, pytanie tylko o programowo modyfikowania SQL generowane przez EF

+0

Nie jestem pewien, czy dobrze odpowiedziałem na pytanie - z tego co wnioskowałem, chcesz wykonać chnage_tracking za każdym razem, gdy aktualizacja odbywa się przez EF. Możliwe, że masz zapisane procsy (posiadające śledzenie, których potrzebujesz) do swoich aktualizacji/dodawania/usuwania, a następnie mapuj je do jednostek EF. Więcej szczegółów tutaj - http://www.entityframeworktutorial.net/entityframework6/code-first-insert-update-delete-stored-procedure-mapping.aspx. Daj mi znać, jeśli przeczytam twoje pytanie źle .. – Developer

Odpowiedz

0

[edit po wyjaśnieniu OP]

myślę, że łatwiej jest set up Change Tracking on the server side i nie bałagan z zapytaniami EF. Śledzenie zmian wkrótce umieścić:

Plusy:

  • lekki
  • konfiguracja jest dość łatwe
  • wsparcie dla synchronizacji
  • nadal częścią transakcji (cofnięty, jeśli transakcja nie powiedzie)
  • Brak zależności od agenta SQL
  • spowoduje przechwycenie wprowadzonych zmian niepożądane działanie normalne zmiana ORM (procedury przechowywane wywoływane przez kod, wszystkie zmiany pochodzące spoza aplikacji)

Wady:

  • nie nadają się do badania, które wymagają więcej informacji
  • trochę wolniej , ponieważ wykonano synchronicznie (w przeciwieństwie do natury asynchronicznej CDC)

[Odpowiedź oryginalna]

Jednym ze sposobów jest dodanie informacji o zmianach/śledzeniu wzdłuż "normalnych" zmian i posiadanie ich wszystkich w ramach jednej transakcji.

Można zastąpić metodę DbContext za pomocą i dodać kod do informacji o śledzeniu. Odwołanie ChangeTracker pozwala znaleźć wszystkie obiekty, które mają określony stan (dodane, zaktualizowane, usunięte, niezmodyfikowane), a tym samym mogą również zapisać typ wprowadzonej zmiany. Podano pełny przykład pracy: here.

pakiet

Nuget wydaje się tam być, aby pomóc w auding - TrackerEnabledDbContext

Zaletą tego podejścia jest to, że łatwo oznaczyć typów elementów, tak, że niektóre informacje nie są zbadane (albo implementować interfejs lub użyj jakiegoś niestandardowego atrybutu).

Kolejną zaletą jest to, że można jeszcze bardziej precyzyjnie dostrajać śledzenie zmian, wyraźnie określając atrybuty śledzenia w swoich właściwościach.

Wadą jest to, że transakcje będą dłuższe, a blokowanie niektórych tabel będzie dłuższe, co może prowadzić do problemów z wydajnością (zależy to w dużej mierze od liczby transakcji w danym okresie).

Rozwiązanie to będzie przechwytywać tylko zmiany z kodu kontekstowego (EF), a nie inne zmiany, które są wykonywane bezpośrednio w bazie danych lub za pomocą procedur przechowywanych (niezależnie od tego, że są wywoływane z zewnętrznego procesu lub EF) .

Innym podejściem jest użycie strony serwera (SQL) Change Data Capture, która przechwytuje wszystkie zmiany wprowadzone w tabelach, dla których ta funkcja jest włączona. Jednym z ważnych aspektów CDC jest zachowanie, gdy struktura tabeli poddawanej audytowi ulega zmianom. Aby uzyskać więcej informacji, przeczytaj this article.

podejście po stronie serwera ma dwie główne zalety:

  • jest szybsza, ponieważ odbywa się asynchronicznie
  • bardziej wiarygodne, jeżeli zmiany danych pochodzą z różnych źródeł (ręcznie ETL, procedury przechowywanej itp).
+0

Pytanie dotyczy konkretnie śledzenia zmian w serwerze SQL, pozwól mi zaktualizować pytanie, aby uzyskać jasność. –

+0

Myślę, że nie mogę być bardziej jasne, śledzenie zmian jest już używane ... –

5

Niestety, Entity Framework 6 nie ma wbudowanego wsparcia dla SQL Server Change Tracking. Jednakże ujawnia możliwości przechwytywania, które umożliwiają modyfikowanie SQL, który generuje przed wykonaniem. Podczas zmiany SQL, który generuje ORM, należy robić to ostrożnie i tylko z uzasadnionego powodu, są absolutnie przypadki, w których jest to właściwe rozwiązanie.

EF6 udostępnia typ IDbCommandInterceptor, który umożliwia przechwycenie całego przebiegu zapytania. Prosta potrzeba wdrożenia tego interfejsu i zarejestrowania przechwytywacza za pomocą EF.

Warto zauważyć, że ramy wezwie NonQueryExecuting przed każdym INSERT, UPDATE i DELETE, co czyni go doskonałym miejscem, aby zaczepić w śledzeniu zmian.

Jako prosty przykład rozważmy tę przechwytywania:

public class ChangeTrackingInterceptor : IDbCommandInterceptor 
{ 
    private byte[] GetChangeTrackingContext() 
    { 
     // TODO: Return the appropriate change tracking context data 
     return new byte[] { 0, 1, 2, 3 }; 
    } 

    public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext) 
    { 
     command.CommandText = "WITH CHANGE_TRACKING_CONTEXT (@change_tracking_context)\r\n" + command.CommandText; 

     // Create the varbinary(128) parameter 
     var parameter = command.CreateParameter(); 
     parameter.DbType = DbType.Binary; 
     parameter.Size = 128; 
     parameter.ParameterName = "@change_tracking_context"; 
     parameter.Value = GetChangeTrackingContext(); 
     command.Parameters.Add(parameter); 
    } 

    public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext) 
    { 
    } 

    public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext) 
    { 
    } 

    public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext) 
    { 
    } 

    public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext) 
    { 
    } 

    public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext) 
    { 
    } 
} 

Kiedy EF generuje jakieś zapytania, który zmienia stan DB, to wywołanie tej metody przed wykonaniem zapytania. Daje to możliwość wstrzyknięcia niestandardowego kontekstu śledzenia zmian za pomocą standardowego kodu SQL.

Aby zarejestrować przechwytywania EF, wystarczy zadzwonić DbInterception.Add gdzieś w kodzie startowym:

var changeTrackingInterceptor = new ChangeTrackingInterceptor(); 
DbInterception.Add(changeTrackingInterceptor); 

Nie ma mnóstwo doskonałej dokumentacji interfejsu IDbCommandInterceptor, ale this MSDN article jest dobrym miejscem, aby rozpocząć.

+0

to sposób, w jaki próbowałem go uruchomić, ale nie mogłem tego zrobić. Infact nie był w stanie w ogóle uruchomić interceptora, a następnie musiał opuścić pracę z powodu złego stanu zdrowia. Spróbuję ponownie, jak tylko wrócę do pracy i zostawię tutaj informację zwrotną, więc do tej pory nie została ona przetestowana z mojej strony –