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