Entity Framework 4 and Transactions: Do uncommitted changes affect select results within a transaction?
If I use transactions with Entity Framework 4 like so, will selects on the modified set reflect the newly saved customer IDs within the transaction, or will this generate the same id for each customer?
using ( System.Data.Common.DbTransaction trans = new DbTransaction() )
{
foreach( var customer in CustomersToSave )
{
// Calculate lowest ID available
var id_Q开发者_如何学JAVAuery = (from c in Customers
select c.ID).Distinct();
var lowest_ID_Available =
(from p1 in id_Query
from p2 in id_Query.Where(a => a == p1 + 1).DefaultIfEmpty()
where p2 == 0
select p1).Min();
... Create a customer with the lowest_ID_Available
}
trans.Commit()
}
This will work only if you call SaveChanges
after adding each customer which is pretty bad solution. Also this will not run in transaction because DbTransaction
alone doesn't work until created from DbConnection
by calling BeginTransaction
. Use TransactionScope
instead.
Another issue is concurrency. Depending on your transaction isolation level other concurrent transactions will either wait for this one to complete or will be able to use same ids as the current transaction.
This is usually handled by separate table which contains only counters. You will create stored procedure to get next counter for given key (table name). The procedure will use atomic update which will set return value and increment current counter in the same time.
Usage of this procedure depends on your requirements. If you require continuos sequence of generated numbers (without holes from rollbacks) then you must lock the record in this special table only for current transaction. If your requirement is only to get unique number but you don't need to have sequence without holes you can use concurrent access.
Example of stored procedure locking the record (if you don't need locking remove hints in update statement):
CREATE PROCEDURE [dbo].[GetNextSequenceValue]
@SequenceType VARCHAR(20)
AS
BEGIN
DECLARE @Result INT
UPDATE [dbo].[Sequences] WITH (ROWLOCK, UPDLOCK)
SET @Result = Value = Value + 1
WHERE SequenceType = @SequenceType
RETURN @Result
END
精彩评论