1+ using Microsoft . EntityFrameworkCore ;
2+ using Microsoft . Extensions . DependencyInjection ;
3+ using System ;
4+ using System . Collections . Generic ;
5+ using System . IO ;
6+ using System . Threading . Tasks ;
7+ using Xunit ;
8+
9+ namespace BlazarTech . QueryableValues . SqlServer . Tests . Integration
10+ {
11+ public class CustomServiceProviderTests
12+ {
13+ public class DummyDbContext : DbContext
14+ {
15+ public DummyDbContext ( DbContextOptions options ) : base ( options )
16+ {
17+ }
18+ }
19+
20+ private static IServiceProvider BuildGoodInternalServiceProvider ( )
21+ {
22+ var services = new ServiceCollection ( )
23+ . AddEntityFrameworkSqlServer ( )
24+ . AddQueryableValuesSqlServer ( ) ;
25+
26+ return services . BuildServiceProvider ( ) ;
27+ }
28+
29+ private static IServiceProvider BuildBadInternalServiceProvider ( )
30+ {
31+ var services = new ServiceCollection ( )
32+ . AddEntityFrameworkSqlServer ( ) ;
33+
34+ return services . BuildServiceProvider ( ) ;
35+ }
36+
37+ private static string GetConnectionString ( )
38+ {
39+ var databaseName = $ "DummyDb{ Guid . NewGuid ( ) : N} ";
40+ var databaseFilePath = Path . Combine ( Path . GetTempPath ( ) , $ "{ databaseName } .mdf") ;
41+ return @$ "Server=(localdb)\MSSQLLocalDB;Integrated Security=true;Connection Timeout=190;Database={ databaseName } ;AttachDbFileName={ databaseFilePath } ";
42+ }
43+
44+ private static async Task CleanUpDbAsync ( DbContext dbContext )
45+ {
46+ try
47+ {
48+ await dbContext . Database . EnsureDeletedAsync ( ) ;
49+ }
50+ catch
51+ {
52+ }
53+ }
54+
55+ [ Fact ]
56+ public async Task BadInternalServiceProvider ( )
57+ {
58+ var internalServiceProvider = BuildBadInternalServiceProvider ( ) ;
59+ var connectionString = GetConnectionString ( ) ;
60+ var services = new ServiceCollection ( ) ;
61+
62+ services . AddDbContext < DummyDbContext > ( builder =>
63+ {
64+ builder
65+ . UseInternalServiceProvider ( internalServiceProvider )
66+ . UseSqlServer ( connectionString , options =>
67+ {
68+ options . UseQueryableValues ( ) ;
69+ } ) ;
70+ } ) ;
71+
72+ var serviceProvider = services . BuildServiceProvider ( ) ;
73+ var dbContext = serviceProvider . GetRequiredService < DummyDbContext > ( ) ;
74+
75+ try
76+ {
77+ await dbContext . Database . EnsureCreatedAsync ( ) ;
78+
79+ var values = new [ ] { 1 , 2 , 3 } ;
80+
81+ var exception = await Assert . ThrowsAnyAsync < InvalidOperationException > ( async ( ) =>
82+ {
83+ await dbContext . AsQueryableValues ( values ) . ToListAsync ( ) ;
84+ } ) ;
85+
86+ Assert . StartsWith ( "QueryableValues have not been configured for " , exception . Message ) ;
87+ }
88+ finally
89+ {
90+ await CleanUpDbAsync ( dbContext ) ;
91+ }
92+ }
93+
94+ #if ! EFCORE3
95+ [ Theory ]
96+ [ InlineData ( SqlServerSerialization . UseJson ) ]
97+ [ InlineData ( SqlServerSerialization . UseXml ) ]
98+ public async Task GoodInternalServiceProviderWithConfiguration ( SqlServerSerialization sqlServerSerializationOption )
99+ {
100+ var internalServiceProvider = BuildGoodInternalServiceProvider ( ) ;
101+ var connectionString = GetConnectionString ( ) ;
102+ var services = new ServiceCollection ( ) ;
103+ var logEntries = new List < string > ( ) ;
104+
105+ services . AddDbContext < DummyDbContext > ( builder =>
106+ {
107+ builder
108+ . UseInternalServiceProvider ( internalServiceProvider )
109+ . UseSqlServer ( connectionString , options =>
110+ {
111+ options . UseQueryableValues ( options =>
112+ {
113+ options . Serialization ( sqlServerSerializationOption ) ;
114+ } ) ;
115+ } )
116+ . LogTo ( logEntry => { logEntries . Add ( logEntry ) ; } , Microsoft . Extensions . Logging . LogLevel . Information ) ;
117+ } ) ;
118+
119+ var serviceProvider = services . BuildServiceProvider ( ) ;
120+ var dbContext = serviceProvider . GetRequiredService < DummyDbContext > ( ) ;
121+
122+ try
123+ {
124+ await dbContext . Database . EnsureCreatedAsync ( ) ;
125+
126+ var values = new [ ] { 1 , 2 , 3 } ;
127+ var valuesResult = await dbContext . AsQueryableValues ( values ) . ToListAsync ( ) ;
128+ Assert . Equal ( values , valuesResult ) ;
129+
130+ switch ( sqlServerSerializationOption )
131+ {
132+ case SqlServerSerialization . UseJson :
133+ Assert . Contains ( logEntries , i => i . Contains ( "FROM OPENJSON(@p0)" ) ) ;
134+ break ;
135+ case SqlServerSerialization . UseXml :
136+ Assert . Contains ( logEntries , i => i . Contains ( "FROM @p0.nodes" ) ) ;
137+ break ;
138+ default :
139+ throw new NotImplementedException ( ) ;
140+ }
141+ }
142+ finally
143+ {
144+ await CleanUpDbAsync ( dbContext ) ;
145+ }
146+ }
147+ #endif
148+ }
149+ }
0 commit comments