J'ai une procédure stockée que j'ai besoin d'exécuter dans le cadre d'une étendue de transaction plus large en utilisant Entity Framework 4.0. Voici une démonstration rapide du scénario que j'ai:Comment puis-je retourner les mises à jour effectuées dans une procédure stockée dans un TransactionScope à l'aide d'Entity Framework?
private void button1_Click(object sender, EventArgs e)
{
using (var scope = GetTransaction(IsolationLevel.Serializable))
{
var model = new SPUpdateTestEntities();
var rows = model.TestTables.ToList();
Debug.WriteLine("rows:");
foreach (var row in rows)
{
Debug.WriteLine(row);
}
var random = new Random();
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var result = new string(
Enumerable.Repeat(chars, 8)
.Select(s => s[random.Next(s.Length)])
.ToArray());
model.UpdateTestTable(rows[random.Next(rows.Count())].Id, result, random.Next());
model.SaveChanges();
var rowsAgain = model.TestTables.ToList();
Debug.WriteLine("rowsAgain:");
foreach (var row in rowsAgain)
{
Debug.WriteLine(row);
}
scope.Complete();
}
}
private TransactionScope GetTransaction(IsolationLevel isolationLevel)
{
var transactionOptions = new TransactionOptions();
transactionOptions.IsolationLevel = isolationLevel;
transactionOptions.Timeout = TransactionManager.MaximumTimeout;
return new TransactionScope(TransactionScopeOption.Required, transactionOptions);
}
Le but de la procédure stockée UpdateTestTable
est à la fois insérer et mettre à jour les enregistrements du TestTable.
ALTER PROCEDURE [dbo].[UpdateTestTable]
@Id AS INTEGER,
@Text as VARCHAR(255),
@Number AS INTEGER
AS
BEGIN
INSERT INTO TestTable(Text, Number)
VALUES (CONVERT(varchar(255), NEWID()), ABS(CHECKSUM(NewId())) % 14)
UPDATE TestTable
SET Text = @Text, Number = @Number
WHERE Id = @Id
END
Le comportement que je me attends est de allRowsAgain
pour contenir toutes les modifications qui ont été apportées à UpdateTestTable
. Le comportement actuel que j'obtiens est que les enregistrements insérés sont renvoyés mais les mises à jour des enregistrements existants ne le sont pas.
J'ai essayé les niveaux d'isolement Serializable
(comme indiqué), ReadComitted
, et ReadUncomitted
mais cela ne fait pas de différence sur le résultat comme je l'espérais.
Edit: J'ai ajouté quelques instructions de débogage pour rendre les résultats un peu plus clair, voici la sortie:
Première course:
rows:
Id:2 - Number:1 - Text:Hello
rowsAgain:
Id:2 - Number:1 - Text:Hello
Id:19 - Number:1 - Text:0B22C83C-58E9-403C-96B4-FB3940E1F250
Deuxième course:
rows:
Id:2 - Number:2135368409 - Text:CQCXCTAY
Id:19 - Number:1 - Text:0B22C83C-58E9-403C-96B4-FB3940E1F250
rowsAgain:
Id:2 - Number:2135368409 - Text:CQCXCTAY
Id:19 - Number:1 - Text:0B22C83C-58E9-403C-96B4-FB3940E1F250
Id:20 - Number:8 - Text:D5A6684B-D140-415F-A81B-36705915FAF6
Merci, Ant
peut-être parce que l'étendue de la transaction est en attente des modifications de la base de données jusqu'à la fin de la transaction? – Claies
Je suppose que vous avez probablement raison, mais j'espérais être en mesure d'utiliser les valeurs avant de commettre la transaction. Aussi je suis curieux de savoir pourquoi la ligne insérée est disponible mais pas la mise à jour. Peut-être la mise en cache EF? –
semble étrange, pour certain. – Claies