2016-11-30 5 views
14

У меня есть модель Entity Framework 6 Code First, созданная из существующей базы данных SQL Server. В базе данных используется отслеживание изменений SQL Server, поэтому для всех операций обработки данных, генерируемых из EF, я хочу установить контекст отслеживания изменений, чтобы отличать их от изменений, сделанных другими внешними процессами. Обычно это делается в T-SQL, как
WITH CHANGE_TRACKING_CONTEXT (@source_id) UPDATE <table>...Поддержка отслеживания изменений SQL Server с Entity Framework 6

Единственное, что я могу думать о том, чтобы предварять выше пункт SQL в SQL генерируемой EF. Хотя кажется, что желание изменить SQL, сгенерированный ORM, сомнительно. Тем не менее, даже если я хочу, я не знаю, где это можно сделать. Может ли EF Command Interception служить цели?

Вопрос касается использования функции отслеживания изменений SQL Server наряду с EF (не отслеживанием изменений EF). С точки зрения EF, речь идет только о программной модификации SQL генерируется EF

+0

Не уверен, правильно ли я получил ваш вопрос - из того, что я предположил, вы хотите выполнить chnage_tracking всякий раз, когда обновление выполняется через EF. Возможно, вы можете сохранить procs (с отслеживанием, который вам нужен) для ваших обновлений/добавления/удаления, а затем сопоставить их с объектами EF. Подробнее здесь - http://www.entityframeworktutorial.net/entityframework6/code-first-insert-update-delete-stored-procedure-mapping.aspx. Дайте мне знать, если я неправильно прочитал ваш вопрос. – Developer

ответ

0

[редактировать после уточнения параметров порядка]

Я думаю, что легче set up Change Tracking on the server side и не связываться с EF запросов. Отслеживание изменений в ближайшее время ставить:

Плюсы:

  • легкая установка
  • довольно легко поддержка
  • для синхронизации
  • еще часть сделки (откат, если транзакция не может)
  • нет зависимости от агента SQL
  • будет улавливать измененные изменения сторона нормальная операция изменения ORM (хранимые процедуры, вызываемые кода, все изменения, происходящие за пределами вашего приложения)

Минусы:

  • не подходит для аудита, которая требует больше информации
  • немного медленнее , поскольку он выполнялся синхронно (в отличие от асинхронного характера CDC)

[оригинал ответа]

Один из способов - добавить информацию об изменениях/отслеживании в соответствии с вашими «нормальными» изменениями и охватить все их в рамках одной транзакции.

Вы можете переопределить DbContext 's SaveChanges и добавить код для отслеживания. Ссылка ChangeTracker позволяет найти все объекты, которые имеют определенное состояние (добавлено, обновлено, удалено, немодифицировано) и, таким образом, также может сохранить тип выполненных изменений. Полный рабочий пример представлен here.

NuGet пакет, кажется, там, чтобы помочь вам с аудирования - TrackerEnabledDbContext

Преимущество этого подхода заключается в том, что вы легко пометить типы сущностей, так что некоторая информация не проверяются (либо реализовать интерфейс или используйте некоторый пользовательский атрибут).

Еще одно преимущество заключается в том, что вы можете еще больше настроить отслеживание изменений, явно указав атрибуты отслеживания на свои свойства.

Недостаток, который я вижу, заключается в том, что транзакции будут длиннее, а блокировка некоторых таблиц будет более продолжительной, что может привести к проблемам с производительностью (это в большой степени зависит от количества транзакций за период времени).

Кроме того, это решение поймает только изменения из вашего контекстного кода (EF), а не другие изменения, которые выполняются непосредственно с базой данных или с помощью хранимых процедур (независимо от того, что они вызываются из внешнего процесса или EF) ,

Другой подход заключается в использовании серверной части (SQL) Change Data Capture, которая улавливает все изменения, внесенные в таблицы, для которых включена эта функция. Одним из важных аспектов CDC является поведение, когда изменяется структура проверенной таблицы. Для получения дополнительной информации читайте this article.

сторона подход Сервер имеет два основных преимущества:

  • быстрее, так как это делается асинхронно
  • более надежным, если данные изменения происходят из различных источников (вручную, ETL, хранимые процедуры и т.д.).
+0

Вопрос конкретно в SQL Server Change Tracking, позвольте мне уточнить вопрос для ясности –

+0

Я думаю, что я не могу быть более ясным, отслеживание изменений уже используется ... –

5

К сожалению, Entity Framework 6 не имеет встроенной поддержки отслеживания изменений SQL Server. Тем не менее, он предоставляет возможности перехвата, которые позволяют вам изменять SQL, который он создает до выполнения. При изменении SQL, создаваемого ORM, это то, что нужно делать осторожно и только по уважительной причине, есть абсолютно случаи, когда это подходящее решение.

EF6 предоставляет тип IDbCommandInterceptor, который дает вам крючки во весь конвейер запросов. Вам просто необходимо реализовать этот интерфейс и зарегистрировать ваш перехватчик с помощью EF.

Следует отметить, что основы будет NonQueryExecuting перед каждым INSERT, UPDATE и DELETE, что делает его прекрасным местом для Вас, чтобы зацепить в отслеживании изменений.

В качестве простого примера рассмотрим этот перехватчик:

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) 
    { 
    } 
} 

Когда EF генерирует любой запрос, который изменяет состояние БД, он будет вызывать этот метод перед выполнением запроса. Это дает вам возможность внедрить свой настраиваемый контекст отслеживания изменений с помощью стандартного SQL.

Чтобы зарегистрировать перехватчик с EF, просто вызовите DbInterception.Add где-то в коде запуска:

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

Там не тонна большой документации на интерфейсе IDbCommandInterceptor, но this MSDN article является хорошим местом для начала.

+0

это то, как я пытался заставить его работать, но не смог этого сделать. Infact не смог полностью запустить перехватчик, а затем пришлось покинуть работу из-за плохого состояния здоровья. Повторите попытку, как только я вернусь к работе и оставлю отзыв здесь, так что до сих пор это непроверено с моей стороны –