コード例 #1
0
		public IExecuteResult Execute(IProvider provider, object[] parentArgs, object[] userArgs)
		{
			if(parentArgs == null && !(this.parameters == null || this.parameters.Count == 0))
			{
				throw Error.ArgumentNull("arguments");
			}

			// construct new copy of query info
			List<SqlParameterInfo> spis = new List<SqlParameterInfo>(this.queryInfo.Parameters);

			// add call arguments
			for(int i = 0, n = this.parameters.Count; i < n; i++)
			{
				spis.Add(new SqlParameterInfo(this.parameters[i], parentArgs[i]));
			}

			QueryInfo qi = new QueryInfo(
				this.queryInfo.Query,
				this.queryInfo.CommandText,
				spis.AsReadOnly(),
				this.queryInfo.ResultShape,
				this.queryInfo.ResultType
				);

			// execute query
			return provider.Execute(null, qi, this.factory, parentArgs, userArgs, subQueries, null);
		}
コード例 #2
0
		internal AdoCompiledQuery(IReaderProvider provider, Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, ICompiledSubQuery[] subQueries)
		{
			this.originalShape = provider.Services.Context.LoadOptions;
			this.query = query;
			this.queryInfos = queryInfos;
			this.factory = factory;
			this.subQueries = subQueries;
		}
コード例 #3
0
		internal CompiledSubQuery(QueryInfo queryInfo, IObjectReaderFactory factory, ReadOnlyCollection<Provider.NodeTypes.SqlParameter> parameters, 
								  ICompiledSubQuery[] subQueries)
		{
			this.queryInfo = queryInfo;
			this.factory = factory;
			this.parameters = parameters;
			this.subQueries = subQueries;
		}
コード例 #4
0
ファイル: SqlProvider.cs プロジェクト: modulexcite/LinqToSQL2
		/// <summary>
		/// Executes all queries
		/// </summary>
		/// <param name="query">The query.</param>
		/// <param name="queryInfos">The query infos.</param>
		/// <param name="factory">The factory.</param>
		/// <param name="userArguments">The user arguments.</param>
		/// <param name="subQueries">The sub queries.</param>
		/// <returns></returns>
		IExecuteResult IProvider.ExecuteAll(Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, object[] userArguments, ICompiledSubQuery[] subQueries)
		{
			return this.ExecuteAll(query, queryInfos, factory, userArguments, subQueries);
		}
コード例 #5
0
ファイル: SqlProvider.cs プロジェクト: modulexcite/LinqToSQL2
		IExecuteResult IProvider.Execute(Expression query, QueryInfo queryInfo, IObjectReaderFactory factory, object[] parentArgs, object[] userArgs, ICompiledSubQuery[] subQueries, object lastResult)
		{
			return this.Execute(query, queryInfo, factory, parentArgs, userArgs, subQueries, lastResult);
		}
コード例 #6
0
ファイル: SqlProvider.cs プロジェクト: modulexcite/LinqToSQL2
		/// <summary>
		/// Look for compatibility annotations for the set of providers we
		/// add annotations for.
		/// </summary>
		private void CheckSqlCompatibility(QueryInfo[] queries, SqlNodeAnnotations annotations)
		{
			if(this.Mode == SqlServerProviderMode.Sql2000 ||
				this.Mode == SqlServerProviderMode.SqlCE)
			{
				for(int i = 0, n = queries.Length; i < n; i++)
				{
					CompatibilityCheck.ThrowIfUnsupported(queries[i].Query, annotations, this.Mode);
				}
			}
		}
コード例 #7
0
ファイル: SqlProvider.cs プロジェクト: modulexcite/LinqToSQL2
		private QueryInfo[] BuildQuery(ResultShape resultShape, Type resultType, SqlNode node, ReadOnlyCollection<System.Data.Linq.Provider.NodeTypes.SqlParameter> parentParameters, SqlNodeAnnotations annotations)
		{
			System.Diagnostics.Debug.Assert(resultType != null);
			System.Diagnostics.Debug.Assert(node != null);

			SqlSupersetValidator validator = new SqlSupersetValidator();

			// These are the rules that apply to every SQL tree.
			if(_checkQueries)
			{
				validator.AddValidator(new ColumnTypeValidator()); /* Column CLR Type must agree with its Expressions CLR Type */
				validator.AddValidator(new LiteralValidator()); /* Constrain literal Types */
			}

			validator.Validate(node);

			SqlColumnizer columnizer = new SqlColumnizer();

			// resolve member references
			bool canUseOuterApply = (this.Mode == SqlServerProviderMode.Sql2005 || this.Mode == SqlServerProviderMode.Sql2008 || this.Mode == SqlServerProviderMode.SqlCE);
			SqlBinder binder = new SqlBinder(_translator, _sqlFactory, _services.Model, _services.Context.LoadOptions, columnizer, canUseOuterApply);
			binder.OptimizeLinkExpansions = (_optimizationFlags & OptimizationFlags.OptimizeLinkExpansions) != 0;
			binder.SimplifyCaseStatements = (_optimizationFlags & OptimizationFlags.SimplifyCaseStatements) != 0;
			binder.PreBinder = delegate(SqlNode n)
			{
				// convert methods into known reversable operators
				return PreBindDotNetConverter.Convert(n, _sqlFactory, _services.Model);
			};
			node = binder.Bind(node);
			if(_checkQueries)
			{
				validator.AddValidator(new ExpectNoAliasRefs());
				validator.AddValidator(new ExpectNoSharedExpressions());
			}
			validator.Validate(node);

			node = PostBindDotNetConverter.Convert(node, _sqlFactory, this.Mode);

			// identify true flow of sql data types 
			SqlRetyper retyper = new SqlRetyper(new SqlFactory(_typeProvider, _services.Model));
			node = retyper.Retype(node);
			validator.Validate(node);

			// change CONVERT to special conversions like UNICODE,CHAR,...
			SqlTypeConverter converter = new SqlTypeConverter(_sqlFactory);
			node = converter.Visit(node);
			validator.Validate(node);

			// transform type-sensitive methods such as LEN (to DATALENGTH), ...
			SqlMethodTransformer methodTransformer = new SqlMethodTransformer(_sqlFactory);
			node = methodTransformer.Visit(node);
			validator.Validate(node);

			// convert multisets into separate queries
			SqlMultiplexerOptionType options = (this.Mode == SqlServerProviderMode.Sql2008 ||
											  this.Mode == SqlServerProviderMode.Sql2005 ||
											  this.Mode == SqlServerProviderMode.SqlCE)
				? SqlMultiplexerOptionType.EnableBigJoin : SqlMultiplexerOptionType.None;
			SqlMultiplexer mux = new SqlMultiplexer(options, parentParameters, _sqlFactory);
			node = mux.Multiplex(node);
			validator.Validate(node);

			// convert object construction expressions into flat row projections
			SqlFlattener flattener = new SqlFlattener(_sqlFactory, columnizer);
			node = flattener.Flatten(node);
			validator.Validate(node);

			if(_mode == SqlServerProviderMode.SqlCE)
			{
				SqlRewriteScalarSubqueries rss = new SqlRewriteScalarSubqueries(_sqlFactory);
				node = rss.Rewrite(node);
			}

			// Simplify case statements where all alternatives map to the same thing.
			// Doing this before deflator because the simplified results may lead to
			// more deflation opportunities.
			// Doing this before booleanizer because it may convert CASE statements (non-predicates) into
			// predicate expressions.
			// Doing this before reorderer because it may reduce some orders to constant nodes which should not
			// be passed onto ROW_NUMBER.
			node = SqlCaseSimplifier.Simplify(node, _sqlFactory);

			// Rewrite order-by clauses so that they only occur at the top-most select 
			// or in selects with TOP
			SqlReorderer reorderer = new SqlReorderer(_typeProvider, _sqlFactory);
			node = reorderer.Reorder(node);
			validator.Validate(node);

			// Inject code to turn predicates into bits, and bits into predicates where necessary
			node = SqlBooleanizer.Rationalize(node, _typeProvider, _services.Model);
			if(_checkQueries)
			{
				validator.AddValidator(new ExpectRationalizedBooleans()); /* From now on all boolean expressions should remain rationalized. */
			}
			validator.Validate(node);

			if(_checkQueries)
			{
				validator.AddValidator(new ExpectNoFloatingColumns());
			}

			// turning predicates into bits/ints can change Sql types, propagate changes            
			node = retyper.Retype(node);
			validator.Validate(node);

			// assign aliases to columns
			// we need to do this now so that the sql2k lifters will work
			SqlAliaser aliaser = new SqlAliaser();
			node = aliaser.AssociateColumnsWithAliases(node);
			validator.Validate(node);

			// SQL2K enablers.
			node = SqlLiftWhereClauses.Lift(node, new SqlFactory(_typeProvider, _services.Model));
			node = SqlLiftIndependentRowExpressions.Lift(node);
			node = SqlOuterApplyReducer.Reduce(node, _sqlFactory, annotations);
			node = SqlTopReducer.Reduce(node, annotations, _sqlFactory);

			// resolve references to columns in other scopes by adding them
			// to the intermediate selects
			SqlResolver resolver = new SqlResolver();
			node = resolver.Resolve(node);
			validator.Validate(node);

			// re-assign aliases after resolving (new columns may have been added)
			node = aliaser.AssociateColumnsWithAliases(node);
			validator.Validate(node);

			// fixup union projections
			node = SqlUnionizer.Unionize(node);

			// remove order-by of literals
			node = SqlRemoveConstantOrderBy.Remove(node);

			// throw out unused columns and redundant sub-queries...
			SqlDeflator deflator = new SqlDeflator();
			node = deflator.Deflate(node);
			validator.Validate(node);

			// Positioning after deflator because it may remove unnecessary columns
			// from SELECT projection lists and allow more CROSS APPLYs to be reduced
			// to CROSS JOINs.
			node = SqlCrossApplyToCrossJoin.Reduce(node, annotations, new Enum[] { SqlServerProviderMode.Sql2000 });

			// fixup names for aliases, columns, locals, etc..
			SqlNamer namer = new SqlNamer();
			node = namer.AssignNames(node);
			validator.Validate(node);

			// Convert [N]Text,Image to [N]VarChar(MAX),VarBinary(MAX) where necessary.
			// These new types do not exist on SQL2k, so add annotations.
			LongTypeConverter longTypeConverter = new LongTypeConverter(_sqlFactory);
			node = longTypeConverter.AddConversions(node, annotations);

			// final validation            
			validator.AddValidator(new ExpectNoMethodCalls());
			validator.AddValidator(new ValidateNoInvalidComparison());
			validator.Validate(node);

			SqlParameterizer parameterizer = new SqlParameterizer(_typeProvider, annotations);
			SqlFormatter formatter = new SqlFormatter();
			if(_mode == SqlServerProviderMode.SqlCE ||
				_mode == SqlServerProviderMode.Sql2005 ||
				_mode == SqlServerProviderMode.Sql2008)
			{
				formatter.ParenthesizeTop = true;
			}

			SqlBlock block = node as SqlBlock;
			if(block != null && _mode == SqlServerProviderMode.SqlCE)
			{
				// SQLCE cannot batch multiple statements.
				ReadOnlyCollection<ReadOnlyCollection<SqlParameterInfo>> parameters = parameterizer.ParameterizeBlock(block);
				string[] commands = formatter.FormatBlock(block, false);
				QueryInfo[] queries = new QueryInfo[commands.Length];
				for(int i = 0, n = commands.Length; i < n; i++)
				{
					queries[i] = new QueryInfo(
						block.Statements[i],
						commands[i],
						parameters[i],
						(i < n - 1) ? ResultShape.Return : resultShape,
						(i < n - 1) ? typeof(int) : resultType
						);
				}
				return queries;
			}
			else
			{
				// build only one result
				ReadOnlyCollection<SqlParameterInfo> parameters = parameterizer.Parameterize(node);
				string commandText = formatter.Format(node);
				return new QueryInfo[] {
                    new QueryInfo(node, commandText, parameters, resultShape, resultType)
                    };
			}
		}
コード例 #8
0
ファイル: SqlProvider.cs プロジェクト: modulexcite/LinqToSQL2
		private IExecuteResult ExecuteAll(Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, object[] userArguments, ICompiledSubQuery[] subQueries)
		{
			IExecuteResult result = null;
			object lastResult = null;
			for(int i = 0, n = queryInfos.Length; i < n; i++)
			{
				if(i < n - 1)
				{
					result = this.Execute(query, queryInfos[i], null, null, userArguments, subQueries, lastResult);
				}
				else
				{
					result = this.Execute(query, queryInfos[i], factory, null, userArguments, subQueries, lastResult);
				}
				if(queryInfos[i].ResultShape == ResultShape.Return)
				{
					lastResult = result.ReturnValue;
				}
			}
			return result;
		}
コード例 #9
0
ファイル: SqlProvider.cs プロジェクト: modulexcite/LinqToSQL2
		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);
			}
		}