Multiple write Object Contexts in the same request
Writing to the database from more then one data context in the same request it is bad for several reasons. Here is why:
- Each data context uses a separate database connection. Using more than one data context means using more than one database connection per request. This can hurt overall performance, and puts more pressure on the database.
- Using different data context mean that we cannot take advantage of the database built-in transaction support and have to rely on System.Transactions which is significantly slower.
- We can't rely on the database to ensure transactionally safe view of the data, since we are using several different transactions to access the database. Note that this is the case even when using system.Transactions.
- When using System.Transactions it forcing you to use DTC in order to keep all sessions in the same transaction. Using DTC lead to bad performance and is more brittle than not using it.
- Without using System.Transactions, there is no ability to use transaction across all the session.
For example, let us consider the following code, which is using multiple object contexts to perform a single operation:
public void TransferMoney(Account from, Account to, Money amount) { Dao.Withdraw(from, amount); Dao.Deposit(to, amount); } public void Withdraw(Account account, Money amount) { using(var ctx = new MyBankContext()) { account.MoenyAmount -= amount; ctx.Accounts.Attach(account); ctx.SaveChanges(); } } public void Deposit(Account account, Money amount) { using(var ctx = new MyBankContext()) { account.MoenyAmount += amount; ctx.Accounts.Attach(account); ctx.SaveChanges(); } }
In this example, we call to the database twice, each time from different data context. Because of that, we cannot take advantage of the database native transaction support, since each operation happen in a different transaction. Our choices are to either operate essentially without transactions (in which case, money can literally disappear in the air), or participate in a distributed transaction (System.Transaction).
The solution for this is simple: Use just one data context per request.