예제 #1
0
		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);
			}
		}