al fine di fare un po’ di esperimenti sto usando il “nuovo” (si fa per dire) SqlCe 3.5 SP1 (o come diavolo si chiama… ;-)) ma sono incappato in un fastidioso comportamento che non è semplice da aggirare.
Se cercate di racchiudere una serie di “SqlCeCommand” in un blocco “TransactionScope” vi beccate una sonora Exception che vi informa che “The Connection object cannot be enlisted in the Transaction”… il motivo è molto semplice SqlCe non supporta le transazioni distribuite (nella versione precedente 3.1 non c’era neppure nessun supporto per System.Transactions, quindi non lamentiamoci troppo) quindi se avete più connessioni aperte verso lo stesso db, nonostante la connection string sia dientica, vengono interpretate come distribuite. Quindi questo si schianta:
using( TransactionScope tx = new TransactionScope() )
{
    using( SqlCeConnection cn = new SqlCeConnection( cnStr ) )
    {
        using( SqlCeCommand firstInsert = new SqlCeCommand( cmd, cn ) )
        {
            cn.Open();
            Int32 result = firstInsert.ExecuteNonQuery();
            cn.Close();
        }
    }

    using( SqlCeConnection cn = new SqlCeConnection( cnStr ) )
    {
        using( SqlCeCommand secondInsert = new SqlCeCommand( cmd, cn ) )
        {
            cn.Open();
            Int32 result = secondInsert.ExecuteNonQuery();
            cn.Close();
        }
    }

    tx.Complete();
}

la soluzione è semplice e consta nel condividere la stessa SqlCeConnection, che, bada ben, deve essere aperta prima del primo command e chiusa solo dopo l’ultimo non essendoci connection pooling:
using( TransactionScope tx = new TransactionScope() )
{
    using( SqlCeConnection cn = new SqlCeConnection( cnStr ) )
    {

        cn.Open();

        using( SqlCeCommand firstInsert = new SqlCeCommand( cmd, cn ) )
        {
            Int32 result = firstInsert.ExecuteNonQuery();
        }

        using( SqlCeCommand secondInsert = new SqlCeCommand( cmd, cn ) )
        {
            Int32 result = secondInsert.ExecuteNonQuery();
        }

        cn.Close();

    }

    tx.Complete();
}

Siamo sempre alle solite, se avete un’architettura “figosa” fatta a componenti/servizi realizzare questa cosa nel dal non è cero banale, ma “se po fa” :-D
.m