1+ using EntityFrameworkCore . SqlServer . SimpleBulks . BulkInsert ;
2+ using EntityFrameworkCore . SqlServer . SimpleBulks . Tests . Database ;
3+ using Microsoft . EntityFrameworkCore ;
4+ using Xunit . Abstractions ;
5+
6+ namespace EntityFrameworkCore . SqlServer . SimpleBulks . Tests . DbContextAsyncExtensions ;
7+
8+ [ Collection ( "SqlServerCollection" ) ]
9+ public class BulkInsertTests : BaseTest
10+ {
11+ public BulkInsertTests ( ITestOutputHelper output , SqlServerFixture fixture ) : base ( output , fixture , "EFCoreSimpleBulksTests.BulkInsert" )
12+ {
13+ }
14+
15+ [ Theory ]
16+ [ InlineData ( 1 ) ]
17+ [ InlineData ( 100 ) ]
18+ public async Task Bulk_Insert_Using_Linq_Without_Transaction ( int length )
19+ {
20+ var rows = new List < SingleKeyRow < int > > ( ) ;
21+ var compositeKeyRows = new List < CompositeKeyRow < int , int > > ( ) ;
22+
23+ for ( int i = 0 ; i < length ; i ++ )
24+ {
25+ rows . Add ( new SingleKeyRow < int >
26+ {
27+ Column1 = i ,
28+ Column2 = "" + i ,
29+ Column3 = DateTime . Now ,
30+ Season = Season . Autumn
31+ } ) ;
32+
33+ compositeKeyRows . Add ( new CompositeKeyRow < int , int >
34+ {
35+ Id1 = i ,
36+ Id2 = i ,
37+ Column1 = i ,
38+ Column2 = "" + i ,
39+ Column3 = DateTime . Now ,
40+ Season = Season . Autumn
41+ } ) ;
42+ }
43+
44+ await _context . BulkInsertAsync ( rows ,
45+ row => new { row . Column1 , row . Column2 , row . Column3 , row . Season } ,
46+ options =>
47+ {
48+ options . LogTo = _output . WriteLine ;
49+ } ) ;
50+
51+ await _context . BulkInsertAsync ( compositeKeyRows ,
52+ row => new { row . Id1 , row . Id2 , row . Column1 , row . Column2 , row . Column3 , row . Season } ,
53+ options =>
54+ {
55+ options . LogTo = _output . WriteLine ;
56+ } ) ;
57+
58+
59+ // Assert
60+ var dbRows = _context . SingleKeyRows . AsNoTracking ( ) . ToList ( ) ;
61+ var dbCompositeKeyRows = _context . CompositeKeyRows . AsNoTracking ( ) . ToList ( ) ;
62+
63+ for ( int i = 0 ; i < length ; i ++ )
64+ {
65+ Assert . Equal ( rows [ i ] . Id , dbRows [ i ] . Id ) ;
66+ Assert . Equal ( rows [ i ] . Column1 , dbRows [ i ] . Column1 ) ;
67+ Assert . Equal ( rows [ i ] . Column2 , dbRows [ i ] . Column2 ) ;
68+ Assert . Equal ( rows [ i ] . Column3 , dbRows [ i ] . Column3 ) ;
69+ Assert . Equal ( rows [ i ] . Season , dbRows [ i ] . Season ) ;
70+
71+ Assert . Equal ( compositeKeyRows [ i ] . Id1 , dbCompositeKeyRows [ i ] . Id1 ) ;
72+ Assert . Equal ( compositeKeyRows [ i ] . Id2 , dbCompositeKeyRows [ i ] . Id2 ) ;
73+ Assert . Equal ( compositeKeyRows [ i ] . Column1 , dbCompositeKeyRows [ i ] . Column1 ) ;
74+ Assert . Equal ( compositeKeyRows [ i ] . Column2 , dbCompositeKeyRows [ i ] . Column2 ) ;
75+ Assert . Equal ( compositeKeyRows [ i ] . Column3 , dbCompositeKeyRows [ i ] . Column3 ) ;
76+ Assert . Equal ( compositeKeyRows [ i ] . Season , dbCompositeKeyRows [ i ] . Season ) ;
77+ }
78+ }
79+
80+ [ Theory ]
81+ [ InlineData ( 1 ) ]
82+ [ InlineData ( 100 ) ]
83+ public async Task Bulk_Insert_Using_Linq_With_Transaction_Committed ( int length )
84+ {
85+ var tran = _context . Database . BeginTransaction ( ) ;
86+
87+ var rows = new List < SingleKeyRow < int > > ( ) ;
88+ var compositeKeyRows = new List < CompositeKeyRow < int , int > > ( ) ;
89+
90+ for ( int i = 0 ; i < length ; i ++ )
91+ {
92+ rows . Add ( new SingleKeyRow < int >
93+ {
94+ Column1 = i ,
95+ Column2 = "" + i ,
96+ Column3 = DateTime . Now
97+ } ) ;
98+
99+ compositeKeyRows . Add ( new CompositeKeyRow < int , int >
100+ {
101+ Id1 = i ,
102+ Id2 = i ,
103+ Column1 = i ,
104+ Column2 = "" + i ,
105+ Column3 = DateTime . Now
106+ } ) ;
107+ }
108+
109+ await _context . BulkInsertAsync ( rows ,
110+ row => new { row . Column1 , row . Column2 , row . Column3 } ) ;
111+
112+ await _context . BulkInsertAsync ( compositeKeyRows ,
113+ row => new { row . Id1 , row . Id2 , row . Column1 , row . Column2 , row . Column3 } ) ;
114+
115+ tran . Commit ( ) ;
116+
117+ // Assert
118+ var dbRows = _context . SingleKeyRows . AsNoTracking ( ) . ToList ( ) ;
119+ var dbCompositeKeyRows = _context . CompositeKeyRows . AsNoTracking ( ) . ToList ( ) ;
120+
121+ for ( int i = 0 ; i < length ; i ++ )
122+ {
123+ Assert . Equal ( rows [ i ] . Id , dbRows [ i ] . Id ) ;
124+ Assert . Equal ( rows [ i ] . Column1 , dbRows [ i ] . Column1 ) ;
125+ Assert . Equal ( rows [ i ] . Column2 , dbRows [ i ] . Column2 ) ;
126+ Assert . Equal ( rows [ i ] . Column3 , dbRows [ i ] . Column3 ) ;
127+
128+ Assert . Equal ( compositeKeyRows [ i ] . Id1 , dbCompositeKeyRows [ i ] . Id1 ) ;
129+ Assert . Equal ( compositeKeyRows [ i ] . Id2 , dbCompositeKeyRows [ i ] . Id2 ) ;
130+ Assert . Equal ( compositeKeyRows [ i ] . Column1 , dbCompositeKeyRows [ i ] . Column1 ) ;
131+ Assert . Equal ( compositeKeyRows [ i ] . Column2 , dbCompositeKeyRows [ i ] . Column2 ) ;
132+ Assert . Equal ( compositeKeyRows [ i ] . Column3 , dbCompositeKeyRows [ i ] . Column3 ) ;
133+ }
134+ }
135+
136+ [ Theory ]
137+ [ InlineData ( 1 ) ]
138+ [ InlineData ( 100 ) ]
139+ public async Task Bulk_Insert_Using_Linq_With_Transaction_RolledBack ( int length )
140+ {
141+ var tran = _context . Database . BeginTransaction ( ) ;
142+
143+ var rows = new List < SingleKeyRow < int > > ( ) ;
144+ var compositeKeyRows = new List < CompositeKeyRow < int , int > > ( ) ;
145+
146+ for ( int i = 0 ; i < length ; i ++ )
147+ {
148+ rows . Add ( new SingleKeyRow < int >
149+ {
150+ Column1 = i ,
151+ Column2 = "" + i ,
152+ Column3 = DateTime . Now
153+ } ) ;
154+
155+ compositeKeyRows . Add ( new CompositeKeyRow < int , int >
156+ {
157+ Id1 = i ,
158+ Id2 = i ,
159+ Column1 = i ,
160+ Column2 = "" + i ,
161+ Column3 = DateTime . Now
162+ } ) ;
163+ }
164+
165+ await _context . BulkInsertAsync ( rows ,
166+ row => new { row . Column1 , row . Column2 , row . Column3 } ) ;
167+
168+ await _context . BulkInsertAsync ( compositeKeyRows ,
169+ row => new { row . Id1 , row . Id2 , row . Column1 , row . Column2 , row . Column3 } ) ;
170+
171+ tran . Rollback ( ) ;
172+
173+ // Assert
174+ var dbRows = _context . SingleKeyRows . AsNoTracking ( ) . ToList ( ) ;
175+ var dbCompositeKeyRows = _context . CompositeKeyRows . AsNoTracking ( ) . ToList ( ) ;
176+
177+ Assert . Empty ( dbRows ) ;
178+ Assert . Empty ( dbCompositeKeyRows ) ;
179+ }
180+
181+ [ Theory ]
182+ [ InlineData ( 1 ) ]
183+ [ InlineData ( 100 ) ]
184+ public async Task Bulk_Insert_KeepIdentity ( int length )
185+ {
186+ var configurationEntries = new List < ConfigurationEntry > ( ) ;
187+
188+ for ( int i = 0 ; i < length ; i ++ )
189+ {
190+ configurationEntries . Add ( new ConfigurationEntry
191+ {
192+ Id = Guid . NewGuid ( ) ,
193+ Key = $ "Key{ i } ",
194+ Value = $ "Value{ i } ",
195+ Description = string . Empty ,
196+ CreatedDateTime = DateTimeOffset . Now ,
197+ } ) ;
198+ }
199+
200+ await _context . BulkInsertAsync ( configurationEntries , options =>
201+ {
202+ options . KeepIdentity = true ;
203+ options . LogTo = _output . WriteLine ;
204+ } ) ;
205+
206+ // Assert
207+ configurationEntries = configurationEntries . OrderBy ( x => x . Id ) . ToList ( ) ;
208+ var configurationEntriesInDb = _context . Set < ConfigurationEntry > ( ) . AsNoTracking ( ) . ToList ( ) . OrderBy ( x => x . Id ) . ToList ( ) ;
209+
210+ for ( int i = 0 ; i < length ; i ++ )
211+ {
212+ Assert . Equal ( configurationEntries [ i ] . Id , configurationEntriesInDb [ i ] . Id ) ;
213+ Assert . Equal ( configurationEntries [ i ] . Key , configurationEntriesInDb [ i ] . Key ) ;
214+ Assert . Equal ( configurationEntries [ i ] . Value , configurationEntriesInDb [ i ] . Value ) ;
215+ Assert . Equal ( configurationEntries [ i ] . Description , configurationEntriesInDb [ i ] . Description ) ;
216+ Assert . Equal ( configurationEntries [ i ] . CreatedDateTime , configurationEntriesInDb [ i ] . CreatedDateTime ) ;
217+ }
218+ }
219+
220+ [ Theory ]
221+ [ InlineData ( 1 ) ]
222+ [ InlineData ( 100 ) ]
223+ public async Task Bulk_Insert_Return_DbGeneratedId ( int length )
224+ {
225+ var configurationEntries = new List < ConfigurationEntry > ( ) ;
226+
227+ for ( int i = 0 ; i < length ; i ++ )
228+ {
229+ configurationEntries . Add ( new ConfigurationEntry
230+ {
231+ Key = $ "Key{ i } ",
232+ Value = $ "Value{ i } ",
233+ Description = string . Empty ,
234+ CreatedDateTime = DateTimeOffset . Now ,
235+ } ) ;
236+ }
237+
238+ await _context . BulkInsertAsync ( configurationEntries , options =>
239+ {
240+ options . LogTo = _output . WriteLine ;
241+ } ) ;
242+
243+ // Assert
244+ configurationEntries = configurationEntries . OrderBy ( x => x . Id ) . ToList ( ) ;
245+ var configurationEntriesInDb = _context . Set < ConfigurationEntry > ( ) . AsNoTracking ( ) . ToList ( ) . OrderBy ( x => x . Id ) . ToList ( ) ;
246+
247+ for ( int i = 0 ; i < length ; i ++ )
248+ {
249+ Assert . NotEqual ( Guid . Empty , configurationEntriesInDb [ i ] . Id ) ;
250+ Assert . Equal ( configurationEntries [ i ] . Id , configurationEntriesInDb [ i ] . Id ) ;
251+ Assert . Equal ( configurationEntries [ i ] . Key , configurationEntriesInDb [ i ] . Key ) ;
252+ Assert . Equal ( configurationEntries [ i ] . Value , configurationEntriesInDb [ i ] . Value ) ;
253+ Assert . Equal ( configurationEntries [ i ] . Description , configurationEntriesInDb [ i ] . Description ) ;
254+ Assert . Equal ( configurationEntries [ i ] . CreatedDateTime , configurationEntriesInDb [ i ] . CreatedDateTime ) ;
255+ }
256+ }
257+ }
0 commit comments