EF транзакции c # MySQL разъем - PullRequest
0 голосов
/ 20 июля 2011

Мне было интересно, каков наилучший способ или практика для реализации следующего:

У меня есть метод с именем EditUser, который имеет следующее определение:

public void EditUser(user user, Roles role)
    {
        using (TestEntities entities = new TestEntities())
        {
            entities.Connection.Open();
            using (DbTransaction trans = entities.Connection.BeginTransaction())
            {
                try
                {
                    var tmpUser = entities.users.Where(fields => fields.UserId == user.UserId).FirstOrDefault();

                    RoleManagement rm = new RoleManagement();
                    string oldRole = tmpUser.roles.FirstOrDefault().Name;
                    string newRole = rm.GetRoleName(role);

                    if (oldRole == newRole)
                    {
                        entities.users.ApplyCurrentValues(user);
                    }
                    else
                    {
                        rm.UnbindRoles(tmpUser.UserId, entities.Connection);
                        this.DeleteUser(tmpUser.UserId, entities.Connection);
                        this.Register(user, role, entities.Connection);
                    }

                    entities.SaveChanges();
                    trans.Commit();
                }
                catch (Exception ex)
                {
                    trans.Rollback();
                    throw ex;
                }
            }
        }
    }

Как вы можете заметить, я вызываю несколько методов: UnbindRoles, DeleteUser и RegisterUser, где все они должны быть запущены в рамках одной транзакции (той же транзакции, которую выполняет EditUser), в случае сбоя чего-либо мне потребуется выполнить откат.

Теперь моя проблема в основном здесь ... метод RegisterUser также запускает новую транзакцию, поскольку он добавляет пользователя и назначает новому пользователю роль.

Кто-нибудь может описать лучший способ, как это реализовать? Я попытался использовать блок TransactionScope, но он не работает, так как я запускаю это приложение в среде Medium Trust

EDIT

Подтверждение того, что поставщик коннектора MySQL .NET имеет ошибку при использовании TransactionScope в Medium Trust, поскольку я только что проверил сейчас тот же сценарий с использованием базы данных MS SQL Server, и он работает без каких-либо проблем

Ответы [ 2 ]

1 голос
/ 20 июля 2011

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

Несколько способов исправить это:

A) Когда вы создаете область транзакций, вы можете сказать, что они должны создавать ее только в том случае, если она еще не доступна.

B) Вместо того, чтобы делать первый подход, введите один из частных методов, скажем, InnerEdit.и InnerRegister, которые содержат логику, но не открывают и не закрывают транзакции, в которых код остается в общедоступных методах Edit и Register.Эти «внутренние» методы можно использовать повторно, в то время как общедоступные содержат инфраструктуру.Если вы переходите ко второму подходу Google для аспектно-ориентированного программирования, это может решить эти «сквозные проблемы»

public void EditUser(user user, Roles role)
{
    using (TestEntities entities = new TestEntities())
    {
        entities.Connection.Open();
        using (DbTransaction trans = entities.Connection.BeginTransaction())
        {
          InnerEditUser(entities, trans);
          InnerThat(entities, trans);
          InnerThis(entities,trans);
          entities.SaveChanges();
          trans.Commit();
        }
    }
 }

Опции TransactionScope MSDN ссылка

0 голосов
/ 20 июля 2011

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

...