Безопасно ли обновлять несколько таблиц с условием столбца ConcurrencyMode = fixed без транзакции с БД? - PullRequest
0 голосов
/ 11 апреля 2019

нам здесь неясно, нужна ли нам транзакция в следующем сценарии, если мы используем ConcurrencyMode = фиксированный или нет.

3 таблицы задействованы:

<User>
UserID              (pk, int)
SessionToken        (uniqueidentifier, nullable, FK onto Session table, in EDMX set to ConcurrencyMode=fixed)

<Journal>
JournalID           (PK, int)
SessionID           (int, FK onto Session table)
JournalAction       (varchar(256))

<Session>
SessionID           (pk, int)
SessionToken        (uniqueidentifier, nullable)
SessionEndTimestamp (datetime, nullable)

Итак, что происходит,когда мы делаем «выход из системы», нам необходимо:

  1. установить для Session.SessionEndTimeStamp значение DateTime.Now
  2. установить для User.SessionToken значение NULL (в настоящее время оно будет установлено равнымзапись нашего Session.SessionToken, чьей записью мы только что манипулировали на шаге 1.)
  3. добавить запись в журнале (в эту сессию)

Мы хотим, чтобы это происходило ТОЛЬКО в случае, если никто другойдо сих пор манипулировал User.SessionToken.В случае, если кто-то другой манипулировал им, это должно привести к сбою таким образом, что ни один из трех упомянутых шагов не будет сохранен в БД.

Мы используем EF 6.1.3.Теперь вопрос в том, сможет ли EF надежно прервать сохранение (без использования транзакции), если мы будем использовать только один контекст, как показано в приведенном ниже коде.

Код будет:

using (var context = new xxxEntities())
{
    var session = context.Sessions.First(x => x.SessionToken == tokenToLogout);
    var user = context.Users.First(p => p.UserID == userID);

    if (user.SessionToken == null)
        throw new Exception("cannot logout, currently not logged in");
    if (user.SessionToken != tokenToLogout)
        throw new Exception("cannot logout, wrong token provided");

    //the 3 write operations that either all should be completed or none written at all in case somebody manipulated user.SessionToken in the meantime
    session.SessionEndTimeStamp = DateTime.Now;     //#1: update
    user.SessionToken = null;                       //#2: update
    context.Journals.Add(new Journal(){Session = session, JournalAction="logout happened"});    //#3: insert

    context.SaveChanges();
}

Я знаю, что если что-то изменится User.SessionToken между тем, будет выброшено исключение из-за установки на User.SessionToken значения ConcurrencyMode = fixed, НО я не уверен, если это МОЖЕТ означать этот сеанс.SessionEndTimeStamp уже зафиксирован в базе данных или запись в журнале уже сделана?

До сих пор у нас была транзакция, связанная с этим, и мы единственные, кто в данный момент манипулирует, но мы обсуждаем удалениетранзакции, где это возможно, и была идея об установке user.SessionToken в ConcurrencyMode = исправлено.Аргумент заключается в том, что мы просто выполняем один «SaveChanges ()», поэтому EF должен обрабатывать, что либо все, либо ничего не сохраняется.

Но я думаю, нам нужна транзакция здесь, иначе не гарантируется, чтополный «откат» произойдет?

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