回答編集履歴

3

追記&訂正

2021/09/18 01:05

投稿

退会済みユーザー
test CHANGED
@@ -60,7 +60,7 @@
60
60
 
61
61
 
62
62
 
63
- **【追記】**
63
+ **【2021/9/17 追記】**
64
64
 
65
65
 
66
66
 
@@ -222,4 +222,4 @@
222
222
 
223
223
 
224
224
 
225
- ロールバックはされてないという結果です。
225
+ ~~ロールバックはされてないという結果です。~~ ← 間違ってました。上の【2021/9/18 訂正&追記】を見てください。ロールバックはされているのですが、キャッシュの問題で最後に 3 に UPDATE されたというのが上の結果です。

2

訂正&追記

2021/09/18 01:05

投稿

退会済みユーザー
test CHANGED
@@ -20,7 +20,39 @@
20
20
 
21
21
 
22
22
 
23
- 質問者さんのコードで 3 つある context.SaveChanges() はすべて「完全に成功」していて、ロールバックは効かないはずです。
23
+ 質問者さんのコードで 3 つある context.SaveChanges() はすべて「完全に成功」していて、~~ロールバックは効かないはずです。~~
24
+
25
+
26
+
27
+ **【2021/9/18 訂正&追記】ここから**
28
+
29
+
30
+
31
+ 間違ってました。context.SaveChanges() はすべて「完全に成功」していても、2 つ目の SaveChanges を囲っている transaction は SaveChanges でコミットされない(保留中の状態にある)ので transaction.Rollback(); でロールバックされるようです。
32
+
33
+
34
+
35
+ コンテキストのキャッシュの問題でした。質問のコードおよび下の【追記】のコードの、
36
+
37
+
38
+
39
+ context.Sequences.Add(seq1); 
40
+
41
+
42
+
43
+ でキャッシュされ、その後 2 箇所ある、
44
+
45
+
46
+
47
+ context.Sequences.Find(seqName)
48
+
49
+
50
+
51
+ ではキャッシュから取得される。ロールバックはキャッシュに反映されないが、コードの Value++ の結果の値(1 回目は 2, 2回目は 3)はキャッシュに反映され Modified マークがついて、SaveChanges によって最終的に 3 に UPDATE されたということでした。
52
+
53
+
54
+
55
+ **【2021/9/18 訂正&追記】ここまで**
24
56
 
25
57
 
26
58
 

1

追記

2021/09/18 00:55

投稿

退会済みユーザー
test CHANGED
@@ -25,3 +25,169 @@
25
25
 
26
26
 
27
27
  テストコードを見直して、上に紹介した記事の「トランザクションを制御する」のサンプルコードのようにして、例えば 2 つ目の SaveChanges で失敗するように細工するとロールバックされて、一回目の SaveChanges は無かったことになるはずです。
28
+
29
+
30
+
31
+ **【追記】**
32
+
33
+
34
+
35
+ 下のコメント欄で「やってみましたけど、最終結果は 3 ですね。ロールバックはされないようです。後で回答欄に詳細を書いておきます」と書いた件です。
36
+
37
+
38
+
39
+ コードは以下の通りで質問者さんのものと同じです。EF Code First でプロジェクトのフォルダに DB を生成したのでその関係がほんのちょっと異なるぐらいです。Visual Studio 2019 のテンプレートで作った .NET 5.0 のコンソールアプリです。
40
+
41
+
42
+
43
+ ```
44
+
45
+ using System;
46
+
47
+ using System.ComponentModel.DataAnnotations;
48
+
49
+ using System.ComponentModel.DataAnnotations.Schema;
50
+
51
+ using Microsoft.EntityFrameworkCore;
52
+
53
+ using Microsoft.Data.Sqlite;
54
+
55
+
56
+
57
+ namespace ConsoleAppSQLite
58
+
59
+ {
60
+
61
+ class Program
62
+
63
+ {
64
+
65
+ static void Main(string[] args)
66
+
67
+ {
68
+
69
+ var seqName = "SEQ1";
70
+
71
+ using (var context = new TestDBContext())
72
+
73
+ {
74
+
75
+ var seq1 = new SequenceValue() { Name = seqName, Value = 1 };
76
+
77
+ context.Sequences.Add(seq1);
78
+
79
+ context.SaveChanges();
80
+
81
+ // OK: 1 が出力される
82
+
83
+ Console.WriteLine(seq1.Value);
84
+
85
+
86
+
87
+ using (var transaction = context.Database.BeginTransaction())
88
+
89
+ {
90
+
91
+ var seq2 = context.Sequences.Find(seqName);
92
+
93
+ seq2.Value++;
94
+
95
+ context.SaveChanges();
96
+
97
+ // OK: 2 が出力される
98
+
99
+ Console.WriteLine(seq2.Value);
100
+
101
+ transaction.Rollback();
102
+
103
+ }
104
+
105
+
106
+
107
+ var seq3 = context.Sequences.Find(seqName);
108
+
109
+ seq3.Value++;
110
+
111
+ context.SaveChanges();
112
+
113
+
114
+
115
+ // NG:ローバックされているので 2 が出力されるはず:実際には3が出力される
116
+
117
+ Console.WriteLine(seq3.Value);
118
+
119
+ }
120
+
121
+ }
122
+
123
+ }
124
+
125
+
126
+
127
+
128
+
129
+ [Table("SEQUENCES")]
130
+
131
+ public class SequenceValue
132
+
133
+ {
134
+
135
+ [Key, Column("NAME")] public string Name { get; set; }
136
+
137
+ [Column("VALUE")] public int Value { get; set; }
138
+
139
+ }
140
+
141
+
142
+
143
+ public class TestDBContext : DbContext
144
+
145
+ {
146
+
147
+ //private SqliteConnection _conn;
148
+
149
+ //public TestDBContext(SqliteConnection conn) { _conn = conn; }
150
+
151
+ protected override void OnConfiguring(DbContextOptionsBuilder builder)
152
+
153
+ {
154
+
155
+ var path = @"C:\Users\surfe\Documents\Visual Studio 2019\Core5App\ConsoleAppSQLite\ConsoleAppSQLite\test.db";
156
+
157
+ var connStr = "Data Source=" + path;
158
+
159
+
160
+
161
+ builder.UseSqlite(connStr);
162
+
163
+
164
+
165
+ }
166
+
167
+ public DbSet<SequenceValue> Sequences { get; set; }
168
+
169
+ }
170
+
171
+ }
172
+
173
+ ```
174
+
175
+
176
+
177
+ 実行結果は以下の通り(質問者さんと同じ):
178
+
179
+
180
+
181
+ ![イメージ説明](6f2d027ea9708472bdcd4c1350240323.jpeg)
182
+
183
+
184
+
185
+ DB Browser for SQLite で結果を見ると 3 です(実行する前は NAME, VALUE ともカラです):
186
+
187
+
188
+
189
+ ![イメージ説明](ac835097f610d79d316a5208aebe9b72.jpeg)
190
+
191
+
192
+
193
+ ロールバックはされてないという結果です。