Транзакция Entity Framework - PullRequest
       5

Транзакция Entity Framework

2 голосов
/ 01 февраля 2012

У меня есть программа, которая работает в двух экземплярах на двух серверах.Мне нужно выбрать и обновить записи БД в программе, поэтому мне нужна блокировка таблицы или транзакция из EF, в противном случае каждая копия программы может выбирать и изменять одни и те же записи.В то время как первая копия вносит изменения в БД, другая не должна запускать тот же раздел кода.

Я обнаружил TransactionScope в EF, но он не работает должным образом, потому что во время работы первой копии я могу сделать множество выборок и обновлений для этих таблиц в студии SQL Server MGM.

У меня есть короткий кодовый код, пожалуйста, подтвердите его:

using (TransactionScope transaction = new TransactionScope())
{
    //select some records which aren't locked by the other copy of the program
    //condition: Locked==null
    recipientsList = (from c in context.Recipients
                      where
                          c.SentToPlatform == false && c.PopupID != null &&
                          c.Message.MessageStatus == 2 && c.Locked == null
                      select c).Take(piecePerMinute).ToList();

    foreach (var recipient in recipientsList)
    {
        //i need make some changes on the record, prevent it from the other copy of program
        //I need to change locked column to true
        recipient.Locked = true;
        recipient.LockBy = ipAddress;
        Console.Write("I");
        Thread.Sleep(1000);
    }

    //close transaction
    try
    {
        context.SaveChanges();
        transaction.Complete();
    } catch (Exception ex )
    {


    }
}

Ответы [ 3 ]

2 голосов
/ 01 февраля 2012

Технически вам нужна длинная транзакция с более высоким уровнем изоляции, чем Read Committed (уровень по умолчанию). Мне не хватает информации, чтобы знать, хотите ли вы RepeatableRead или Serialzable (чтобы избежать фантомных вставок).

Вы можете выполнить то, что вы просите, выполнив что-то вроде этого:

var opt = new TransactionOptions();
    opt.IsolationLevel = IsolationLevel.Serializable;

using (var scope = new TransactionScope(TransactionScopeOption.Required, opt) ){

   //read table code

   //write table code

   //save context & complete scope

}

С учетом сказанного, Я очень сомневаюсь, что это то, что вы на самом деле хотите . Сериализуемые транзакции могут блокировать большую часть вашей базы данных. Что это значит? Вот как Microsoft описывает сериализуемую транзакцию:

SERIALIZABLE указывает следующее:

  • Операторы не могут читать данные, которые были изменены, но еще не зафиксированы другими транзакциями.
  • Никакие другие транзакции не могут изменять данные, прочитанные текущей транзакцией, до тех пор, пока текущая транзакция не завершится.
  • Другие транзакции не могут вставлять новые строки со значениями ключей, которые попадают в диапазон ключей, считываемых любыми инструкциями в текущей транзакции, пока текущая транзакция не завершится.

Блокировки диапазона помещаются в диапазон значений ключа, которые соответствуют условиям поиска каждого оператора, выполняемого в транзакции. Это блокирует другие транзакции от обновления или вставки любых строк, которые соответствуют требованиям любого из операторов, выполняемых текущим сделка.

....

Поскольку параллелизм ниже, используйте эту опцию только при необходимости .

Как указывает @Bertie, структура сущностей построена на основе оптимистичной модели параллелизма. Существует множество причин для использования оптимистичного параллелизма (OC) и множества шаблонов для решения неизбежных коллизий. ОК делает тебя выше и веселее. Использование сериализованных транзакций для всего оставит вас, как Брюса Уиллиса, в 12 обезьянах - наполненных кусочками торазина в слюнявых слюнявцах по всему полу вашей мягкой комнаты. Вы не хотите этого, теперь вы?

1 голос
/ 01 февраля 2012

вам нужно вручную заблокировать таблицу с помощью SQL.Я нашел этот пост, я думаю, что это то, что вам нужно.но это не то, что удовлетворяет ..

Блокировка таблицы с помощью выбора в Entity Framework

РЕДАКТИРОВАТЬ:

        using (var ts = new TransactionScope())
        {
            var db = new Db();

            var asd = from x in db.MyTable
                      where x.Id == 1
                      select x;

            asd.First().Name = "test2";
            db.SaveChanges();    // if you're here with the debugger the table is locked
        } 
        // and now its unlocked and you can do a select again

internal class Db : DbContext
{
    public Db()
    {
        Database.DefaultConnectionFactory = new SqlConnectionFactory();
        //Database.SetInitializer(new DropCreateDatabaseIfModelChanges<Db>());
        Database.Connection.ConnectionString =
            "yourconnectionstring;";
    }
    public DbSet<MyTable> MyTable { get; set; }
}

internal class MyTable
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime MyTime { get; set; }
}

РЕДАКТИРОВАТЬ2:

Я немного поиграл с EF и TransactionScope, вот мои результаты:

using (var ts = new TransactionScope())
{
    var db = new Db();

    var asd = from x in db.MyTable
                where x.Id == 1
                select x;

    db.SaveChanges(); // you still can fire selects in the studio

    asd.First().Name = "test2"; // now a change is made but not written to the transaction
    db.SaveChanges(); // after this call you can't fire selects in the management studio, the table is locked

    var asd2 = from x in db.MyTable
                where x.Id == 1
                select x;

    asd2.First().Name = "test3";
    db.SaveChanges(); // the table still is locked
}
// now you can do selects again, the table is unlocked
0 голосов
/ 01 февраля 2012

То, к чему это сводится, является Оптимистическим Параллелизмом.Вам нужен способ гарантировать, что каждое приложение знает, когда данные изменились под ним, а затем создать стратегию обращения с ними.Я настоятельно рекомендую прочитать это:

http://msdn.microsoft.com/en-us/library/bb738618.aspx

И вот эти, если они помогут:

http://blogs.msdn.com/b/cesardelatorre/archive/2008/09/04/updating-data-using-entity-framework-in-n-tier-and-n-layer-applications-short-lived-ef-contexts.aspx

http://blogs.msdn.com/b/cesardelatorre/archive/2008/09/05/optimistic-concurrency-updates-using-entity-framework-in-n-tier-and-n-layer-applications-part-2.aspx

Надеюсь, это поможет - дайте мне знать, если есть что-то конкретное, что вам нужно уточнить!

Счастливое кодирование,
Приветствия,
Крис.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...