99using System . Collections . Generic ;
1010using System . Data ;
1111using System . Data . Common ;
12+ using System . Linq . Expressions ;
1213using System . Reflection ;
1314using System . Text ;
1415
@@ -65,7 +66,7 @@ public QueryFutureBatch(DbContext context)
6566 public void ExecuteQueries ( )
6667 {
6768#if EF5 || EF6
68- var connection = ( EntityConnection ) Context . Connection ;
69+ var connection = ( EntityConnection ) Context . Connection ;
6970#elif EFCORE
7071 var connection = Context . Database . GetDbConnection ( ) ;
7172#endif
@@ -135,6 +136,10 @@ protected DbCommand CreateCommandCombined()
135136 var sb = new StringBuilder ( ) ;
136137 var queryCount = 1 ;
137138
139+ var isOracle = command . GetType ( ) . FullName . Contains ( "Oracle.DataAccess" ) ;
140+ var isOracleManaged = command . GetType ( ) . FullName . Contains ( "Oracle.ManagedDataAccess" ) ;
141+ var isOracleDevArt = command . GetType ( ) . FullName . Contains ( "Devart" ) ;
142+
138143 foreach ( var query in Queries )
139144 {
140145 // GENERATE SQL
@@ -158,43 +163,35 @@ protected DbCommand CreateCommandCombined()
158163 sql = sql . Replace ( "@" + oldValue , "@" + newValue ) ;
159164 }
160165#elif EF6
166+ var commandTextAndParameter = query . Query . GetCommandTextAndParameters ( ) ;
161167
162- var objectQuery = query . Query ;
163- var stateField = objectQuery . GetType ( ) . BaseType . GetField ( "_state" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
164- var state = stateField . GetValue ( objectQuery ) ;
165- var getExecutionPlanMethod = state . GetType ( ) . GetMethod ( "GetExecutionPlan" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
166- var getExecutionPlan = getExecutionPlanMethod . Invoke ( state , new object [ ] { null } ) ;
167- var prepareEntityCommandMethod = getExecutionPlan . GetType ( ) . GetMethod ( "PrepareEntityCommand" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
168-
169- string sql = "" ;
170- using ( EntityCommand entityCommand = ( EntityCommand ) prepareEntityCommandMethod . Invoke ( getExecutionPlan , new object [ ] { objectQuery . Context , objectQuery . Parameters } ) )
171- {
172- var getCommandDefinitionMethod = entityCommand . GetType ( ) . GetMethod ( "GetCommandDefinition" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
173- var getCommandDefinition = getCommandDefinitionMethod . Invoke ( entityCommand , new object [ 0 ] ) ;
174168
175- var prepareEntityCommandBeforeExecutionMethod = getCommandDefinition . GetType ( ) . GetMethod ( "PrepareEntityCommandBeforeExecution" , BindingFlags . NonPublic | BindingFlags . Instance ) ;
176- var prepareEntityCommandBeforeExecution = ( DbCommand ) prepareEntityCommandBeforeExecutionMethod . Invoke ( getCommandDefinition , new object [ ] { entityCommand } ) ;
169+ var sql = commandTextAndParameter . Item1 ;
170+ var parameters = commandTextAndParameter . Item2 ;
177171
178- sql = prepareEntityCommandBeforeExecution . CommandText ;
179- var parameters = prepareEntityCommandBeforeExecution . Parameters ;
180-
181- // UPDATE parameter name
182- foreach ( DbParameter parameter in parameters )
172+ // UPDATE parameter name
173+ foreach ( DbParameter parameter in parameters )
174+ {
175+ var oldValue = parameter . ParameterName ;
176+ if ( oldValue . StartsWith ( "@" ) )
183177 {
184- var oldValue = parameter . ParameterName ;
185- if ( oldValue . StartsWith ( "@" ) )
186- {
187- oldValue = oldValue . Substring ( 1 ) ;
188- }
189- var newValue = string . Concat ( "Z_" , queryCount , "_" , oldValue ) ;
178+ oldValue = oldValue . Substring ( 1 ) ;
179+ }
180+ var newValue = string . Concat ( "Z_" , queryCount , "_" , oldValue ) ;
190181
191- // CREATE parameter
192- var dbParameter = command . CreateParameter ( ) ;
193- dbParameter . ParameterName = newValue ;
194- dbParameter . Value = parameter . Value ;
195- command . Parameters . Add ( dbParameter ) ;
182+ // CREATE parameter
183+ var dbParameter = command . CreateParameter ( ) ;
184+ dbParameter . ParameterName = newValue ;
185+ dbParameter . Value = parameter . Value ;
186+ command . Parameters . Add ( dbParameter ) ;
196187
197- // REPLACE parameter with new value
188+ // REPLACE parameter with new value
189+ if ( isOracle || isOracleManaged || isOracleDevArt )
190+ {
191+ sql = sql . Replace ( ":" + oldValue , ":" + newValue ) ;
192+ }
193+ else
194+ {
198195 sql = sql . Replace ( "@" + oldValue , "@" + newValue ) ;
199196 }
200197 }
@@ -206,26 +203,66 @@ protected DbCommand CreateCommandCombined()
206203 var parameters = queryCommand . Parameters ;
207204
208205 // UPDATE parameter name
209- foreach ( var parameter in queryContext . ParameterValues )
206+ foreach ( var relationalParameter in queryCommand . Parameters )
210207 {
211- var oldValue = parameter . Key ;
208+ var parameter = queryContext . ParameterValues [ relationalParameter . InvariantName ] ;
209+
210+ var oldValue = relationalParameter . InvariantName ;
212211 var newValue = string . Concat ( "Z_" , queryCount , "_" , oldValue ) ;
213212
214213 // CREATE parameter
215214 var dbParameter = command . CreateParameter ( ) ;
216215 dbParameter . ParameterName = newValue ;
217- dbParameter . Value = parameter . Value ;
216+ dbParameter . Value = parameter ;
218217 command . Parameters . Add ( dbParameter ) ;
219218
220219 // REPLACE parameter with new value
221- sql = sql . Replace ( "@" + oldValue , "@" + newValue ) ;
220+ if ( isOracle || isOracleManaged || isOracleDevArt )
221+ {
222+ sql = sql . Replace ( ":" + oldValue , ":" + newValue ) ;
223+ }
224+ else
225+ {
226+ sql = sql . Replace ( "@" + oldValue , "@" + newValue ) ;
227+ }
222228 }
223229#endif
224230
225231
226232
227233 sb . AppendLine ( string . Concat ( "-- EF+ Query Future: " , queryCount , " of " , Queries . Count ) ) ;
228- sb . AppendLine ( sql ) ;
234+
235+ if ( isOracle || isOracleManaged || isOracleDevArt )
236+ {
237+ var parameterName = "zzz_cursor_" + queryCount ;
238+ sb . AppendLine ( "open :" + parameterName + " for " + sql ) ;
239+ var param = command . CreateParameter ( ) ;
240+ param . ParameterName = parameterName ;
241+ param . Direction = ParameterDirection . Output ;
242+ param . Value = DBNull . Value ;
243+
244+ if ( isOracle )
245+ {
246+ SetOracleDbType ( command . GetType ( ) . Assembly , param , 121 ) ;
247+ }
248+ else if ( isOracleManaged )
249+ {
250+ SetOracleManagedDbType ( command . GetType ( ) . Assembly , param , 121 ) ;
251+ }
252+ else if ( isOracleDevArt )
253+ {
254+ SetOracleDevArtDbType ( command . GetType ( ) . Assembly , param , 7 ) ;
255+ }
256+
257+
258+ command . Parameters . Add ( param ) ;
259+ }
260+ else
261+ {
262+ sb . AppendLine ( sql ) ;
263+ }
264+
265+
229266 sb . Append ( ";" ) ; // SQL Server, SQL Azure, MySQL
230267 sb . AppendLine ( ) ;
231268 sb . AppendLine ( ) ;
@@ -235,7 +272,85 @@ protected DbCommand CreateCommandCombined()
235272
236273 command . CommandText = sb . ToString ( ) ;
237274
275+ if ( isOracle || isOracleManaged || isOracleDevArt )
276+ {
277+ var bindByNameProperty = command . GetType ( ) . GetProperty ( "BindByName" ) ?? command . GetType ( ) . GetProperty ( "PassParametersByName" ) ;
278+ bindByNameProperty . SetValue ( command , true , null ) ;
279+
280+ command . CommandText = "BEGIN" + Environment . NewLine + command . CommandText + Environment . NewLine + "END;" ;
281+ }
282+
238283 return command ;
239284 }
285+
286+ private static Action < DbParameter , object > _SetOracleDbType ;
287+ private static Action < DbParameter , object > _SetOracleManagedDbType ;
288+ private static Action < DbParameter , object > _SetOracleDevArtDbType ;
289+
290+ public static void SetOracleManagedDbType ( Assembly assembly , DbParameter dbParameter , object type )
291+ {
292+ if ( _SetOracleManagedDbType == null )
293+ {
294+ var dbtype = assembly . GetType ( "Oracle.ManagedDataAccess.Client.OracleDbType" ) ;
295+ var dbParameterType = assembly . GetType ( "Oracle.ManagedDataAccess.Client.OracleParameter" ) ;
296+ var propertyInfo = dbParameter . GetType ( ) . GetProperty ( "OracleDbType" ) ;
297+
298+ var parameter = Expression . Parameter ( typeof ( DbParameter ) ) ;
299+ var parameterConvert = Expression . Convert ( parameter , dbParameterType ) ;
300+ var parameterValue = Expression . Parameter ( typeof ( object ) ) ;
301+ var parameterValueConvert = Expression . Convert ( parameterValue , dbtype ) ;
302+
303+ var property = Expression . Property ( parameterConvert , propertyInfo ) ;
304+ var expression = Expression . Assign ( property , parameterValueConvert ) ;
305+
306+ _SetOracleManagedDbType = Expression . Lambda < Action < DbParameter , object > > ( expression , parameter , parameterValue ) . Compile ( ) ;
307+ }
308+
309+ _SetOracleManagedDbType ( dbParameter , type ) ;
310+ }
311+
312+ public static void SetOracleDbType ( Assembly assembly , DbParameter dbParameter , object type )
313+ {
314+ if ( _SetOracleDbType == null )
315+ {
316+ var dbtype = assembly . GetType ( "Oracle.DataAccess.Client.OracleDbType" ) ;
317+ var dbParameterType = assembly . GetType ( "Oracle.DataAccess.Client.OracleParameter" ) ;
318+ var propertyInfo = dbParameter . GetType ( ) . GetProperty ( "OracleDbType" ) ;
319+
320+ var parameter = Expression . Parameter ( typeof ( DbParameter ) ) ;
321+ var parameterConvert = Expression . Convert ( parameter , dbParameterType ) ;
322+ var parameterValue = Expression . Parameter ( typeof ( object ) ) ;
323+ var parameterValueConvert = Expression . Convert ( parameterValue , dbtype ) ;
324+
325+ var property = Expression . Property ( parameterConvert , propertyInfo ) ;
326+ var expression = Expression . Assign ( property , parameterValueConvert ) ;
327+
328+ _SetOracleDbType = Expression . Lambda < Action < DbParameter , object > > ( expression , parameter , parameterValue ) . Compile ( ) ;
329+ }
330+
331+ _SetOracleDbType ( dbParameter , type ) ;
332+ }
333+
334+ public static void SetOracleDevArtDbType ( Assembly assembly , DbParameter dbParameter , object type )
335+ {
336+ if ( _SetOracleDevArtDbType == null )
337+ {
338+ var dbtype = assembly . GetType ( "Devart.Data.Oracle.OracleDbType" ) ;
339+ var dbParameterType = assembly . GetType ( "Devart.Data.Oracle.OracleParameter" ) ;
340+ var propertyInfo = dbParameter . GetType ( ) . GetProperty ( "OracleDbType" ) ;
341+
342+ var parameter = Expression . Parameter ( typeof ( DbParameter ) ) ;
343+ var parameterConvert = Expression . Convert ( parameter , dbParameterType ) ;
344+ var parameterValue = Expression . Parameter ( typeof ( object ) ) ;
345+ var parameterValueConvert = Expression . Convert ( parameterValue , dbtype ) ;
346+
347+ var property = Expression . Property ( parameterConvert , propertyInfo ) ;
348+ var expression = Expression . Assign ( property , parameterValueConvert ) ;
349+
350+ _SetOracleDevArtDbType = Expression . Lambda < Action < DbParameter , object > > ( expression , parameter , parameterValue ) . Compile ( ) ;
351+ }
352+
353+ _SetOracleDevArtDbType ( dbParameter , type ) ;
354+ }
240355 }
241356}
0 commit comments