Как создать транзакцию LINQ to SQL?

У меня есть фрагмент кода, который включает несколько вложений, но мне нужно выполнить метод подмарантинга, прежде чем я закончу вставку в другие таблицы, чтобы я мог получить Id. Я искал через интернет и не мог найти, как создать транзакцию в linq для sql. Я добавил комментарии в код, где я хочу, чтобы транзакция имела место.

    var created = false;
    try
    {
        var newCharacter = new Character();
        newCharacter.characterName = chracterName;
        newCharacter.characterLevel = 1;
        newCharacter.characterExperience = 0;
        newCharacter.userUsername = userUsername;
        newCharacter.characterClassID = ccslst[0].characterClassID;
        //Open transaction


            ydc.Characters.InsertOnSubmit(newCharacter);
            ydc.SubmitChanges();

            foreach (var ccs in ccslst)
            {
                var cs = new CharacterStat();
                cs.statId = ccs.statID;                        
                cs.statValue = ccs.statValue;
                cs.characterID = newCharacter.characterID;
                ydc.CharacterStats.InsertOnSubmit(cs);
            }                    


            var ccblst = ydc.ClassBodies.Where(cb => cb.characterClassID == newCharacter.characterClassID);
            foreach (var ccb in ccblst)
            {
                var charBody = new CharacterBody();
                charBody.bodyId = ccb.bodyId;
                charBody.bodyPartId = ccb.bodyPartId;
                charBody.characterID = newCharacter.characterID;
                ydc.CharacterBodies.InsertOnSubmit(charBody);
            }
            ydc.SubmitChanges();      
            created = true;
        //Commit transaction
        }
        catch (Exception ex)
        {
            created = false;
            //transaction Rollback;                    
        }
        return created;

EDIT: Забыл упомянуть, что ydc - это мой datacontext

Ответ 1

Оберните все в TransactionScope. Вызовите transaction.Complete() в точке, где вы хотите совершить. Если код выходит из блока без вызова Complete(), транзакция будет отброшена. Однако после просмотра ответа @s_ruchit и повторного изучения вашего кода вы, вероятно, можете переписать это, чтобы не требовать TransactionScope. В первом примере используется TransactionScope с вашим кодом как есть. Второй пример делает некоторые незначительные изменения, но выполняет ту же цель.

Место, где вам нужно использовать TransactionScope, - это когда вы читаете значение из базы данных и используете его для установки нового значения добавляемого объекта. В этом случае транзакция LINQ не будет охватывать первое прочитанное, а только позднее представить новое значение. Поскольку вы используете значение из чтения для вычисления нового значения для записи, вам нужно, чтобы чтение было обернуто в одну транзакцию, чтобы другой читатель не вычислил одно и то же значение и не устранил ваши изменения. В вашем случае вы делаете только записи, поэтому стандартная транзакция LINQ должна работать.

Пример 1:

var created = false;

using (var transaction = new TransactionScope())
{
    try
    {
        var newCharacter = new Character();
        newCharacter.characterName = chracterName;
        newCharacter.characterLevel = 1;
        newCharacter.characterExperience = 0;
        newCharacter.userUsername = userUsername;
        newCharacter.characterClassID = ccslst[0].characterClassID;

        ydc.Characters.InsertOnSubmit(newCharacter);
        ydc.SubmitChanges();

        foreach (var ccs in ccslst)
        {
            var cs = new CharacterStat();
            cs.statId = ccs.statID;                        
            cs.statValue = ccs.statValue;
            cs.characterID = newCharacter.characterID;
            ydc.CharacterStats.InsertOnSubmit(cs);
        }                    

        var ccblst = ydc.ClassBodies.Where(cb => cb.characterClassID == newCharacter.characterClassID);
        foreach (var ccb in ccblst)
        {
            var charBody = new CharacterBody();
            charBody.bodyId = ccb.bodyId;
            charBody.bodyPartId = ccb.bodyPartId;
            charBody.characterID = newCharacter.characterID;
            ydc.CharacterBodies.InsertOnSubmit(charBody);
        }
        ydc.SubmitChanges();      
        created = true;

        transaction.Complete();
    }
    catch (Exception ex)
    {
        created = false;
    }
}
return created;

Пример 2:

    try
    {
        var newCharacter = new Character();
        newCharacter.characterName = chracterName;
        newCharacter.characterLevel = 1;
        newCharacter.characterExperience = 0;
        newCharacter.userUsername = userUsername;
        newCharacter.characterClassID = ccslst[0].characterClassID;

        ydc.Characters.InsertOnSubmit(newCharacter);

        foreach (var ccs in ccslst)
        {
            var cs = new CharacterStat();
            cs.statId = ccs.statID;                        
            cs.statValue = ccs.statValue;
            newCharacter.CharacterStats.Add(cs);
        }                    

        var ccblst = ydc.ClassBodies.Where(cb => cb.characterClassID == newCharacter.characterClassID);
        foreach (var ccb in ccblst)
        {
            var charBody = new CharacterBody();
            charBody.bodyId = ccb.bodyId;
            charBody.bodyPartId = ccb.bodyPartId;
            newCharacter.CharacterBodies.Add(charBody);
        }
        ydc.SubmitChanges();      
        created = true;
    }
    catch (Exception ex)
    {
        created = false;
    }

Ответ 2

Вам не нужно выполнять явную реализацию транзакций при использовании LINQ to SQL. По умолчанию все операции с БД завершаются транзакцией.

Пример:

AppDataContext db = new AppDataContext();

<In memory operation 1 on db>
<In memory operation 2 on db>
<In memory operation 3 on db>
<In memory operation 4 on db>

db.SubmitChanges();

Все операции между инициализацией dC DataContext и db.SubmitChanges() обернуты вокруг транзакции базы данных с помощью .Net, гарантируя, что ваша база данных будет согласованной и целостность свойств поддерживается в таблицах.

Прочтите статью Скотт Гатри здесь: http://weblogs.asp.net/scottgu/archive/2007/07/11/linq-to-sql-part-4-updating-our-database.aspx