private IExecuteResult Execute(Expression query, QueryInfo queryInfo, IObjectReaderFactory factory, object[] parentArgs, object[] userArgs, ICompiledSubQuery[] subQueries, object lastResult) { this.InitializeProviderMode(); DbConnection con = _conManager.UseConnection(this); try { DbCommand cmd = con.CreateCommand(); cmd.CommandText = queryInfo.CommandText; cmd.Transaction = _conManager.Transaction; cmd.CommandTimeout = _commandTimeout; AssignParameters(cmd, queryInfo.Parameters, userArgs, lastResult); LogCommand(_log, cmd); _queryCount += 1; switch(queryInfo.ResultShape) { default: case ResultShape.Return: { return new ExecuteResult(cmd, queryInfo.Parameters, null, cmd.ExecuteNonQuery(), true); } case ResultShape.Singleton: { DbDataReader reader = cmd.ExecuteReader(); IObjectReader objReader = factory.Create(reader, true, this, parentArgs, userArgs, subQueries); _conManager.UseConnection(objReader.Session); try { IEnumerable sequence = (IEnumerable)Activator.CreateInstance( typeof(OneTimeEnumerable<>).MakeGenericType(queryInfo.ResultType), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new object[] { objReader }, null ); object value = null; MethodCallExpression mce = query as MethodCallExpression; MethodInfo sequenceMethod = null; if(mce != null && ( mce.Method.DeclaringType == typeof(Queryable) || mce.Method.DeclaringType == typeof(Enumerable)) ) { switch(mce.Method.Name) { case "First": case "FirstOrDefault": case "SingleOrDefault": sequenceMethod = TypeSystem.FindSequenceMethod(mce.Method.Name, sequence); break; case "Single": default: sequenceMethod = TypeSystem.FindSequenceMethod("Single", sequence); break; } } else { sequenceMethod = TypeSystem.FindSequenceMethod("SingleOrDefault", sequence); } // When dynamically invoking the sequence method, we want to // return the inner exception if the invocation fails if(sequenceMethod != null) { try { value = sequenceMethod.Invoke(null, new object[] { sequence }); } catch(TargetInvocationException tie) { if(tie.InnerException != null) { throw tie.InnerException; } throw; } } return new ExecuteResult(cmd, queryInfo.Parameters, objReader.Session, value); } finally { objReader.Dispose(); } } case ResultShape.Sequence: { DbDataReader reader = cmd.ExecuteReader(); IObjectReader objReader = factory.Create(reader, true, this, parentArgs, userArgs, subQueries); _conManager.UseConnection(objReader.Session); IEnumerable sequence = (IEnumerable)Activator.CreateInstance( typeof(OneTimeEnumerable<>).MakeGenericType(TypeSystem.GetElementType(queryInfo.ResultType)), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new object[] { objReader }, null ); if(typeof(IQueryable).IsAssignableFrom(queryInfo.ResultType)) { sequence = sequence.AsQueryable(); } ExecuteResult result = new ExecuteResult(cmd, queryInfo.Parameters, objReader.Session); MetaFunction function = this.GetFunction(query); if(function != null && !function.IsComposable) { sequence = (IEnumerable)Activator.CreateInstance( typeof(SingleResult<>).MakeGenericType(TypeSystem.GetElementType(queryInfo.ResultType)), BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new object[] { sequence, result, _services.Context }, null ); } result.ReturnValue = sequence; return result; } case ResultShape.MultipleResults: { DbDataReader reader = cmd.ExecuteReader(); IObjectReaderSession session = _readerCompiler.CreateSession(reader, this, parentArgs, userArgs, subQueries); _conManager.UseConnection(session); MetaFunction function = this.GetFunction(query); ExecuteResult result = new ExecuteResult(cmd, queryInfo.Parameters, session); result.ReturnValue = new MultipleResults(this, function, session, result); return result; } } } finally { _conManager.ReleaseConnection(this); } }