1
+ using System ;
2
+ using System . Data ;
3
+ using System . Linq ;
4
+ using NUnit . Framework ;
5
+ using ServiceStack . DataAnnotations ;
6
+
7
+ namespace ServiceStack . OrmLite . Tests
8
+ {
9
+ [ TestFixture ]
10
+ public class ForeignKeyAttributeTests : OrmLiteTestBase
11
+ {
12
+ [ TestFixtureSetUp ]
13
+ public void Setup ( )
14
+ {
15
+ using ( var dbConn = OpenDbConnection ( ) )
16
+ {
17
+ DropTables ( dbConn ) ;
18
+
19
+ dbConn . DropAndCreateTable < ReferencedType > ( ) ;
20
+ }
21
+ }
22
+
23
+ private void DropTables ( IDbConnection dbConnection )
24
+ {
25
+ if ( dbConnection . TableExists ( "TWODUC" ) ) dbConnection . DropTable < TypeWithOnDeleteAndUpdateCascade > ( ) ;
26
+ if ( dbConnection . TableExists ( "TWODSN" ) ) dbConnection . DropTable < TypeWithOnDeleteSetNull > ( ) ;
27
+ if ( dbConnection . TableExists ( "TWODDF" ) ) dbConnection . DropTable < TypeWithOnDeleteSetDefault > ( ) ;
28
+ if ( dbConnection . TableExists ( "TWODNR" ) ) dbConnection . DropTable < TypeWithOnDeleteRestrict > ( ) ;
29
+ if ( dbConnection . TableExists ( "TWODNA" ) ) dbConnection . DropTable < TypeWithOnDeleteNoAction > ( ) ;
30
+ if ( dbConnection . TableExists ( "TWODC" ) ) dbConnection . DropTable < TypeWithOnDeleteCascade > ( ) ;
31
+ if ( dbConnection . TableExists ( "TWSKF" ) ) dbConnection . DropTable < TypeWithSimpleForeignKey > ( ) ;
32
+ if ( dbConnection . TableExists ( "TWONFKI" ) ) dbConnection . DropTable < TypeWithNoForeignKeyInitially > ( ) ;
33
+ }
34
+
35
+ [ Test ]
36
+ public void CanCreateSimpleForeignKey ( )
37
+ {
38
+ using ( var dbConnection = OpenDbConnection ( ) )
39
+ {
40
+ dbConnection . DropAndCreateTable < TypeWithSimpleForeignKey > ( ) ;
41
+ }
42
+ }
43
+
44
+ [ Test ]
45
+ public void ForeignWithOnDeleteCascadeCreatesOk ( )
46
+ {
47
+ using ( var dbConn = OpenDbConnection ( ) )
48
+ {
49
+ dbConn . DropAndCreateTable < TypeWithOnDeleteCascade > ( ) ;
50
+ }
51
+ }
52
+
53
+ [ Test ]
54
+ public void ForeignWithOnDeleteCascadeWorks ( )
55
+ {
56
+ using ( var dbConnection = OpenDbConnection ( ) )
57
+ {
58
+ dbConnection . DropAndCreateTable < TypeWithOnDeleteCascade > ( ) ;
59
+
60
+ dbConnection . Save ( new ReferencedType { Id = 1 } ) ;
61
+ dbConnection . Save ( new TypeWithOnDeleteCascade { RefId = 1 } ) ;
62
+
63
+ Assert . AreEqual ( 1 , dbConnection . Select < ReferencedType > ( ) . Count ) ;
64
+ Assert . AreEqual ( 1 , dbConnection . Select < TypeWithOnDeleteCascade > ( ) . Count ) ;
65
+
66
+ dbConnection . Delete < ReferencedType > ( r => r . Id == 1 ) ;
67
+
68
+ Assert . AreEqual ( 0 , dbConnection . Select < ReferencedType > ( ) . Count ) ;
69
+ Assert . AreEqual ( 0 , dbConnection . Select < TypeWithOnDeleteCascade > ( ) . Count ) ;
70
+ }
71
+ }
72
+
73
+ [ Test ]
74
+ public void ForeignWithOnDeleteCascadeAndOnUpdateCascadeCreatesOk ( )
75
+ {
76
+ using ( var dbConn = OpenDbConnection ( ) )
77
+ {
78
+ dbConn . DropAndCreateTable < TypeWithOnDeleteAndUpdateCascade > ( ) ;
79
+ }
80
+ }
81
+
82
+ [ Test ]
83
+ public void ForeignWithOnDeleteNoActionCreatesOk ( )
84
+ {
85
+ using ( var dbConn = OpenDbConnection ( ) )
86
+ {
87
+ dbConn . DropAndCreateTable < TypeWithOnDeleteNoAction > ( ) ;
88
+ }
89
+ }
90
+
91
+ [ Test ]
92
+ public void ForeignWithOnDeleteNoActionThrowsException ( )
93
+ {
94
+ using ( var dbConnection = OpenDbConnection ( ) )
95
+ {
96
+ dbConnection . CreateTableIfNotExists < TypeWithOnDeleteNoAction > ( ) ;
97
+
98
+ dbConnection . Save ( new ReferencedType { Id = 1 } ) ;
99
+ dbConnection . Save ( new TypeWithOnDeleteNoAction { RefId = 1 } ) ;
100
+
101
+ Assert . AreEqual ( 1 , dbConnection . Select < ReferencedType > ( ) . Count ) ;
102
+ Assert . AreEqual ( 1 , dbConnection . Select < TypeWithOnDeleteNoAction > ( ) . Count ) ;
103
+
104
+ // Do not want to require reference to dll with exception definition so use catch
105
+ Assert . Catch < Exception > ( ( ) => dbConnection . Delete < ReferencedType > ( r => r . Id == 1 ) ) ;
106
+ }
107
+ }
108
+
109
+ [ Test ]
110
+ public void ForeignWithOnDeleteRestrictCreatesOk ( )
111
+ {
112
+ using ( var dbConn = OpenDbConnection ( ) )
113
+ {
114
+ dbConn . DropAndCreateTable < TypeWithOnDeleteRestrict > ( ) ;
115
+ }
116
+ }
117
+
118
+ [ Test ]
119
+ public void ForeignWithOnDeleteRestrictThrowsException ( )
120
+ {
121
+ using ( var dbConnection = OpenDbConnection ( ) )
122
+ {
123
+ dbConnection . CreateTableIfNotExists < TypeWithOnDeleteRestrict > ( ) ;
124
+
125
+ dbConnection . Save ( new ReferencedType { Id = 1 } ) ;
126
+ dbConnection . Save ( new TypeWithOnDeleteRestrict { RefId = 1 } ) ;
127
+
128
+ Assert . AreEqual ( 1 , dbConnection . Select < ReferencedType > ( ) . Count ) ;
129
+ Assert . AreEqual ( 1 , dbConnection . Select < TypeWithOnDeleteRestrict > ( ) . Count ) ;
130
+
131
+ // Do not want to require reference to dll with exception definition so use catch
132
+ Assert . Catch < Exception > ( ( ) => dbConnection . Delete < ReferencedType > ( r => r . Id == 1 ) ) ;
133
+ }
134
+ }
135
+
136
+ [ Test ]
137
+ public void ForeignWithOnDeleteSetDefaultCreatesOk ( )
138
+ {
139
+ using ( var dbConn = OpenDbConnection ( ) )
140
+ {
141
+ dbConn . DropAndCreateTable < TypeWithOnDeleteSetDefault > ( ) ;
142
+ }
143
+ }
144
+
145
+ [ Test ]
146
+ public void ForeignWithOnDeleteSetDefaultThrowsException ( )
147
+ {
148
+ using ( var dbConnection = OpenDbConnection ( ) )
149
+ {
150
+ dbConnection . CreateTableIfNotExists < TypeWithOnDeleteSetDefault > ( ) ;
151
+
152
+ dbConnection . Save ( new ReferencedType { Id = 1 } ) ;
153
+ dbConnection . Save ( new TypeWithOnDeleteSetDefault { RefId = 1 } ) ;
154
+
155
+ Assert . AreEqual ( 1 , dbConnection . Select < ReferencedType > ( ) . Count ) ;
156
+ Assert . AreEqual ( 1 , dbConnection . Select < TypeWithOnDeleteSetDefault > ( ) . Count ) ;
157
+
158
+ // Do not want to require reference to dll with exception definition so use catch
159
+ Assert . Catch < Exception > ( ( ) => dbConnection . Delete < ReferencedType > ( r => r . Id == 1 ) ) ;
160
+ }
161
+ }
162
+
163
+ [ Test ]
164
+ public void ForeignWithOnDeleteSetNullCreatesOk ( )
165
+ {
166
+ using ( var dbConn = OpenDbConnection ( ) )
167
+ {
168
+ dbConn . DropAndCreateTable < TypeWithOnDeleteSetNull > ( ) ;
169
+ }
170
+ }
171
+
172
+ [ Test ]
173
+ public void ForeignWithOnDeleteSetNullWorks ( )
174
+ {
175
+ using ( var dbConnection = OpenDbConnection ( ) )
176
+ {
177
+ DropTables ( dbConnection ) ;
178
+
179
+ dbConnection . CreateTableIfNotExists < TypeWithOnDeleteSetNull > ( ) ;
180
+
181
+ dbConnection . Save ( new ReferencedType { Id = 1 } ) ;
182
+ dbConnection . Save ( new TypeWithOnDeleteSetNull { RefId = 1 } ) ;
183
+
184
+ Assert . AreEqual ( 1 , dbConnection . Select < ReferencedType > ( ) . Count ) ;
185
+ Assert . AreEqual ( 1 , dbConnection . Select < TypeWithOnDeleteSetNull > ( ) . Count ) ;
186
+
187
+ dbConnection . Delete < ReferencedType > ( r => r . Id == 1 ) ;
188
+
189
+ Assert . AreEqual ( 0 , dbConnection . Select < ReferencedType > ( ) . Count ) ;
190
+ var row = dbConnection . Select < TypeWithOnDeleteSetNull > ( ) . First ( ) ;
191
+ Assert . That ( row . RefId , Is . Null ) ;
192
+ }
193
+ }
194
+
195
+ [ Test , NUnit . Framework . Ignore ( "Base implementation does not allow provider override so cannot work in Oracle" ) ]
196
+ public void CanDropForeignKey ( )
197
+ {
198
+ using ( var dbConnection = OpenDbConnection ( ) )
199
+ {
200
+ dbConnection . DropAndCreateTable < TypeWithOnDeleteNoAction > ( ) ;
201
+ dbConnection . DropForeignKey < TypeWithOnDeleteNoAction > ( "FK_DNA" ) ;
202
+ }
203
+ }
204
+
205
+ [ Test ]
206
+ public void CanAddForeignKey ( )
207
+ {
208
+ using ( var dbConnection = OpenDbConnection ( ) )
209
+ {
210
+ dbConnection . DropAndCreateTable < TypeWithNoForeignKeyInitially > ( ) ;
211
+ dbConnection . AddForeignKey < TypeWithNoForeignKeyInitially , ReferencedType > (
212
+ t => t . RefId , tr => tr . Id , OnFkOption . NoAction , OnFkOption . Cascade , "FK_ADDED" ) ;
213
+ }
214
+ }
215
+ }
216
+
217
+ public class ReferencedType
218
+ {
219
+ public int Id { get ; set ; }
220
+ }
221
+
222
+ [ Alias ( "TWSKF" ) ]
223
+ public class TypeWithSimpleForeignKey
224
+ {
225
+ [ AutoIncrement ]
226
+ public int Id { get ; set ; }
227
+ [ References ( typeof ( ReferencedType ) ) ]
228
+ public int RefId { get ; set ; }
229
+ }
230
+
231
+ [ Alias ( "TWODC" ) ]
232
+ public class TypeWithOnDeleteCascade
233
+ {
234
+ [ AutoIncrement ]
235
+ public int Id { get ; set ; }
236
+
237
+ [ ForeignKey ( typeof ( ReferencedType ) , OnDelete = "CASCADE" , ForeignKeyName = "FK_DC" ) ]
238
+ public int ? RefId { get ; set ; }
239
+ }
240
+
241
+ [ Alias ( "TWODUC" ) ]
242
+ public class TypeWithOnDeleteAndUpdateCascade
243
+ {
244
+ [ AutoIncrement ]
245
+ public int Id { get ; set ; }
246
+
247
+ [ ForeignKey ( typeof ( ReferencedType ) , OnDelete = "CASCADE" , OnUpdate = "CASCADE" , ForeignKeyName = "FK_DC_UC" ) ]
248
+ public int ? RefId { get ; set ; }
249
+ }
250
+
251
+ [ Alias ( "TWODNA" ) ]
252
+ public class TypeWithOnDeleteNoAction
253
+ {
254
+ [ AutoIncrement ]
255
+ public int Id { get ; set ; }
256
+
257
+ [ ForeignKey ( typeof ( ReferencedType ) , OnDelete = "NO ACTION" , ForeignKeyName = "FK_DNA" ) ]
258
+ public int ? RefId { get ; set ; }
259
+ }
260
+
261
+ [ Alias ( "TWODNR" ) ]
262
+ public class TypeWithOnDeleteRestrict
263
+ {
264
+ [ AutoIncrement ]
265
+ public int Id { get ; set ; }
266
+
267
+ [ ForeignKey ( typeof ( ReferencedType ) , OnDelete = "RESTRICT" , ForeignKeyName = "FK_DR" ) ]
268
+ public int ? RefId { get ; set ; }
269
+ }
270
+
271
+ [ Alias ( "TWODDF" ) ]
272
+ public class TypeWithOnDeleteSetDefault
273
+ {
274
+ [ AutoIncrement ]
275
+ public int Id { get ; set ; }
276
+
277
+ [ Default ( typeof ( int ) , "17" ) ]
278
+ [ ForeignKey ( typeof ( ReferencedType ) , OnDelete = "SET DEFAULT" , ForeignKeyName = "FK_DDF" ) ]
279
+ public int RefId { get ; set ; }
280
+ }
281
+
282
+ [ Alias ( "TWODSN" ) ]
283
+ public class TypeWithOnDeleteSetNull
284
+ {
285
+ [ AutoIncrement ]
286
+ public int Id { get ; set ; }
287
+
288
+ [ ForeignKey ( typeof ( ReferencedType ) , OnDelete = "SET NULL" , ForeignKeyName = "FK_SN" ) ]
289
+ public int ? RefId { get ; set ; }
290
+ }
291
+
292
+ [ Alias ( "TWONFKI" ) ]
293
+ public class TypeWithNoForeignKeyInitially
294
+ {
295
+ [ AutoIncrement ]
296
+ public int Id { get ; set ; }
297
+
298
+ public int ? RefId { get ; set ; }
299
+ }
300
+ }
0 commit comments