0

BO(国)と子BO(州)があり、子BO(市)もあります。親BO(国)を更新し、子状態を追加して保存を実行すると、DALで(意図的に)例外が発生したときに、トランザクションがロールバックされません。SqlCEを使用しています。問題を示すサンプルの簡略化されたプロジェクトを添付しています。私は何が間違っているのですか?

テストコード:

    Country originalCountry = null;
    try
    {
        originalCountry = Country.GetCountry(1);
        var country = Country.GetCountry(1);
        country.CountryName = "My new name";
        var state = country.States.AddNew();
        state.StateName = "Dummy state";
        country.States.EndNew(country.States.IndexOf(state));
        country.Save();
    }
    catch (Exception exception)
    {
        var country = Country.GetCountry(1);
        if (originalCountry.CountryName != country.CountryName)
        {
            System.Console.WriteLine("Values ARE NOT the same: " + originalCountry.CountryName + " vs. " + country.CountryName);
        }
        else
        {
            System.Console.WriteLine("Values are the same: " + originalCountry.CountryName + " vs. " + country.CountryName);
        }
    }

Country.cs

[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_Update()
{
    Update();
}

private void Update()
{
    using (var ctx = DalFactory.GetManager())
    {
        var dal = ctx.GetProvider<ICountryDal>();
        using (BypassPropertyChecks)
        {
            var dto = new CountryDto();
            TransferToDto(dto);
            dal.Update(dto);
        }
        FieldManager.UpdateChildren(this);
        throw new Exception("Rollback should occur.");
    }
}

サンプルプロジェクト

4

2 に答える 2

1

SQL CEとトランザクションについての私の理解から、TransactionScopeを使用する場合、それらは単一のデータベース接続でのトランザクションのみをサポートします。

あなたのコードはいくつかのCSLAサンプルによって提案されたモデルに従っているように見えますが、データベース接続の実際の開閉はGetManagerまたはGetProviderの抽象化に隠されているため、それがどのように処理されるかを確実に言う方法はありません。

ただし、SQL CEにはTransactionScopeとのトランザクションにいくつかの制限があるようです。したがって、何らかの形でそれらの制限の1つに違反していないことを確認する必要があります。

于 2013-02-13T05:57:20.580 に答える
0

DalManager(およびConnectionManager)は、参照カウントに依存して、実際の接続をいつ閉じるかを決定します。

ルールはDalManagerを確実に破棄していないため、DalManagerと参照カウントはオフになっています。Fetch操作の1つで作成および開かれた接続で更新が行われるため、UpdateメソッドのTransactionScopeに登録されません。

参照: http: //msdn.microsoft.com/en-us/library/bb896149%28v=sql.100%29.aspx

DalManagerを破棄するには、すべてのルールを変更する必要があります。元のルール:

    protected override void Execute(RuleContext context)
    {
        var name = (string)context.InputPropertyValues[_nameProperty];
        var id = (int)context.InputPropertyValues[_idProperty];
        var dal = DalFactory.GetManager();
        var countryDal = dal.GetProvider<ICountryDal>();
        var exists = countryDal.Exists(id, name);
        if (exists)
        {
            context.AddErrorResult("Country with the same name already exists in the database.");
        }
    }

DalManagerはIDisposableですが、ここでは明示的に破棄されないため、GCが実際にオブジェクトを収集する時期によって異なります。

する必要があります:

    protected override void Execute(RuleContext context)
    {
        var name = (string)context.InputPropertyValues[_nameProperty];
        var id = (int)context.InputPropertyValues[_idProperty];
        using (var dal = DalFactory.GetManager())
        {
            var countryDal = dal.GetProvider<ICountryDal>();
            var exists = countryDal.Exists(id, name);
            if (exists)
            {
                context.AddErrorResult("Country with the same name already exists in the database.");
            }
        }
    }
于 2013-02-13T13:58:04.560 に答える