Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>If you are using multiple contexts each using separate connection and you want to save data to those context in single transaction you must use <code>TransactionScope</code> with distributed transaction (MSDTC). </p> <p>Your linked question is not that case because in that scenario first connection do not modify data so it can be closed prior to starting the connection where data are modified. In your case data are concurrently modified on multiple connection which requires two-phase commit and MSDTC.</p> <p>You can try to solve it with sharing single connection among multiple contexts but that can be quite tricky. I'm not sure how reliable the following sample is but you can give it a try:</p> <pre><code>using (var connection = new SqlConnection(connnectionString)) { var c1 = new Context(connection); var c2 = new Context(connection); c1.MyEntities.Add(new MyEntity() { Name = "A" }); c2.MyEntities.Add(new MyEntity() { Name = "B" }); connection.Open(); using (var scope = new TransactionScope()) { // This is necessary because DbContext doesnt't contain necessary methods ObjectContext obj1 = ((IObjectContextAdapter)c1).ObjectContext; obj1.SaveChanges(SaveOptions.DetectChangesBeforeSave); ObjectContext obj2 = ((IObjectContextAdapter)c2).ObjectContext; obj2.SaveChanges(SaveOptions.DetectChangesBeforeSave); scope.Complete(); // Only after successful commit of both save operations we can accept changes // otherwise in rollback caused by second context the changes from the first // context will be already accepted = lost obj1.AcceptAllChanges(); obj2.AcceptAllChanges(); } } </code></pre> <p>Context constructor is defined as:</p> <pre><code>public Context(DbConnection connection) : base(connection,false) { } </code></pre> <p>The sample itself worked for me but it has multiple problems:</p> <ul> <li>First usage of contexts must be done with closed connection. That is the reason why I'm adding entities prior to opening the connection. </li> <li>I rather open connection manually outside of the transaction but perhaps it is not needed.</li> <li>Both save changes successfully run and <code>Transaction.Current</code> has empty distributed transaction Id so it should be still local.</li> <li>The saving is much more complicated and you must use <code>ObjectContext</code> because <code>DbContext</code> doesn't have all necessary methods.</li> <li>It doesn't have to work in every scenario. Even MSDN claims this:</li> </ul> <blockquote> <p>Promotion of a transaction to a DTC may occur when a connection is closed and reopened within a single transaction. Because the Entity Framework opens and closes the connection automatically, you should consider manually opening and closing the connection to avoid transaction promotion.</p> </blockquote> <p>The problem with DbContext API is that it closes and reopens connection even if you open it manually so it is a opened question if API always correctly identifies if it runs in the context of transaction and do not close connection.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload