Exemplo n.º 1
0
 /// <summary>Checks parameter type and determines if parameter may be used as DB command parameter. 
 /// Sets parameter value SqlUse property to DbParameter or Literal. </summary>
 /// <param name="parameter">Input parameter expression to check.</param>
 public virtual void CheckQueryParameter(ExternalValueExpression parameter)
 {
     var type = parameter.Type;
     if (type.IsNullableValueType())
       type = type.GetUnderlyingType();
     // this includes Guid and enum
     if (type.IsDbPrimitive() || type == typeof(Binary) || type == typeof(TimeSpan)) {
       parameter.SqlUse = ExternalValueSqlUse.Parameter;
       return;
     }
     // if it is a list of primitive types, check if provider support list parameters
     if (type.IsListOfDbPrimitive()) {
       var canUseArrayParam = Driver.Supports(DbFeatures.ArrayParameters)
                            && !DbModel.Config.Options.IsSet(DbOptions.ForceArraysAsLiterals);
       if (canUseArrayParam)
     parameter.SqlUse = ExternalValueSqlUse.Parameter;
       else
     parameter.SqlUse = ExternalValueSqlUse.Literal;
       return;
     }
     // throw error
     var msg = "Sql provider does not support parameter/value type: {0}.";
     if (typeof(System.Collections.IList).IsAssignableFrom(parameter.Type))
       msg += " List/array values are supported only for primitive types.";
     Util.Throw(msg, parameter.Type);
 }
Exemplo n.º 2
0
 public virtual string GetParameter(ExternalValueExpression parameter)
 {
     return "{" + (parameter.LinqParameter.Index + 2) + "}";
 }
Exemplo n.º 3
0
 public override string GetParameter(ExternalValueExpression parameter)
 {
     var baseValue = base.GetParameter(parameter);
       //Handling list-type parameters
       if(!parameter.IsList)
     return baseValue;
       // We use Sql_variant column in table UDT that holds list. It was found that it causes index scan instead of seek
       // So we add CAST here
       var elType = parameter.ListElementType;
       var template = @"(SELECT ""Value"" FROM {0})";
       if (elType == typeof(string))
     template = @"(SELECT CAST(""Value"" AS NVarchar) FROM {0})";
       else if (elType == typeof(Guid))
     template = @"(SELECT CAST(""Value"" AS uniqueidentifier) FROM {0})";
       else if (elType == typeof(long) || elType == typeof(ulong))
     template = @"(SELECT CAST(""Value"" AS bigint) FROM {0})";
       else if (elType.IsInt() || elType.IsEnum)
     template = @"(SELECT CAST(""Value"" AS int) FROM {0})";
       return string.Format(template, baseValue);
 }
Exemplo n.º 4
0
        private TranslatedLinqCommand TranslateNonQuery(LinqCommand command)
        {
            LinqCommandPreprocessor.PreprocessCommand(_dbModel.EntityApp.Model, command);
              var rewriterContext = new TranslationContext(_dbModel, command);
              var cmdInfo = command.Info;
              // convert lambda params into an initial set of ExternalValueExpression objects;
              foreach(var prm in cmdInfo.Lambda.Parameters) {
            var inpParam = new ExternalValueExpression(prm);
            rewriterContext.ExternalValues.Add(inpParam);
              }
              //Analyze/transform base select query
              var exprChain = ExpressionChain.Build(cmdInfo.Lambda.Body);
              var selectExpr = BuildSelectExpression(exprChain, rewriterContext);
              // Analyze external values (parameters?), create DbParameters
              var cmdParams = BuildParameters(command, rewriterContext);
              var flags = command.Info.Flags;
              // If there's at least one parameter that must be converted to literal (ex: value list), we cannot cache the query
              bool canCache = !rewriterContext.ExternalValues.Any(v => v.SqlUse == ExternalValueSqlUse.Literal);
              if (!canCache)
            flags |= LinqCommandFlags.NoQueryCache;

              // !!! Before that, everyting is the same as in TranslateSelect
              var targetEnt = command.TargetEntity;
              var targetTableInfo = _dbModel.GetTable(targetEnt.EntityType);
              TableExpression targetTable;
              bool isSingleTable = selectExpr.Tables.Count == 1 && selectExpr.Tables[0].TableInfo == targetTableInfo;
              if(isSingleTable) {
            targetTable = selectExpr.Tables[0];
              } else
            targetTable = _translator.CreateTable(targetEnt.EntityType, rewriterContext);
              var commandData = new NonQueryLinqCommandData(command, selectExpr, targetTable, isSingleTable);
              // Analyze base query output expression
              var readerBody = selectExpr.Reader.Body;
              switch(command.CommandType) {
            case LinqCommandType.Update:
            case LinqCommandType.Insert:
              Util.Check(readerBody.NodeType == ExpressionType.New, "Query for LINQ {0} command must return New object", commandData.CommandType);
              var newExpr = readerBody as NewExpression;
              var outValues = selectExpr.Operands.ToList();
              for(int i = 0; i < newExpr.Members.Count; i++) {
            var memberName = newExpr.Members[i].Name;
            var memberInfo = targetEnt.GetMember(memberName);
            Util.Check(memberInfo != null, "Member {0} not found in entity {1}.", memberName, targetEnt, targetEnt.EntityType);
            switch(memberInfo.Kind) {
              case MemberKind.Column:
                var col = _translator.CreateColumn(targetTable, memberName, rewriterContext);
                commandData.TargetColumns.Add(col);
                commandData.SelectOutputValues.Add(outValues[i]);
                break;
              case MemberKind.EntityRef:
                var fromKey = memberInfo.ReferenceInfo.FromKey;
                Util.Check(fromKey.ExpandedKeyMembers.Count == 1,
                  "References with composite keys are not supported in LINQ non-query operations. Reference: ", memberName);
                var pkMember = fromKey.ExpandedKeyMembers[0].Member;
                var col2 = _translator.CreateColumn(targetTable, pkMember.MemberName, rewriterContext);
                commandData.TargetColumns.Add(col2);
                commandData.SelectOutputValues.Add(outValues[i]);
                break;
              default:
                Util.Throw("Property cannot be used in the context: {0}.", memberName);
                break;
            }
              }
              break;
            case LinqCommandType.Delete:
              commandData.SelectOutputValues.Add(readerBody); //should return single value - primary key
              break;
              }
              // Build SQL
              var sqlBuilder = new SqlBuilder(_dbModel);
              var sqlStmt = sqlBuilder.BuildNonQuery(commandData);
              var sqlTemplate = sqlStmt.ToString();
              var defaultSql = FormatSql(sqlTemplate, cmdParams);
              return new TranslatedLinqCommand(sqlTemplate, defaultSql, cmdParams, flags);
        }
 private ExternalValueExpression DeriveMemberAccessParameter(ExternalValueExpression oldPrm, MemberInfo memberInfo, TranslationContext context)
 {
     MemberExpression newSource = Expression.MakeMemberAccess(oldPrm.SourceExpression, memberInfo);
       Expression safeNewSource = newSource;
       if(!memberInfo.IsStaticMember() && oldPrm.Type.IsInterface)
     safeNewSource = MakeSafeEntityParameterMemberAccess(newSource);
       return DeriveInputParameter(oldPrm, safeNewSource, context);
 }
 private ExternalValueExpression DeriveInputParameter(ExternalValueExpression oldPrm, Expression newSource, TranslationContext context)
 {
     oldPrm.SqlUseCount--;
       var newPrm = new ExternalValueExpression(newSource);
       newPrm.SqlUseCount++;
       context.ExternalValues.Add(newPrm);
       return newPrm;
 }
 private Expression ConvertArrayToConstant(ExternalValueExpression parameter, TranslationContext context)
 {
     object value = null;
       try {
     //value = parameter.GetValue(null);
       } catch (Exception ex) {
     var msg = "Failed to translate 'Contains' call: supported only for arrays or lists that can be converted to constant list. Inner error: " + ex.Message;
     throw new Exception(msg, ex);
       }
       // do not unregister - it will break parameter sequence
       //UnregisterParameter(parameter, context);
       return Expression.Constant(value);
 }
Exemplo n.º 8
0
 private TranslatedLinqCommand TranslateSelect(LinqCommand command)
 {
     LinqCommandPreprocessor.PreprocessCommand(_dbModel.EntityApp.Model, command);
       var context = new TranslationContext(_dbModel, command);
       var cmdInfo = command.Info;
       // convert lambda params into an initial set of ExternalValueExpression objects;
       foreach (var prm in cmdInfo.Lambda.Parameters) {
     var inpParam = new ExternalValueExpression(prm);
     context.ExternalValues.Add(inpParam);
       }
       //Analyze/transform query expression
       var exprChain = ExpressionChain.Build(cmdInfo.Lambda.Body);
       var selectExpr = BuildSelectExpression(exprChain, context);
       // Analyze external values (parameters?), create DbParameters
       var commandParams = BuildParameters(command, context);
       // If there's at least one parameter that must be converted to literal (ex: value list), we cannot cache the query
       bool canCache = !context.ExternalValues.Any(v => v.SqlUse == ExternalValueSqlUse.Literal);
       if (!canCache)
     command.Info.Flags |= LinqCommandFlags.NoQueryCache;
       //Build SQL, compile object materializer
       var sqlBuilder = new SqlBuilder(_dbModel);
       var sqlStatement = sqlBuilder.BuildSelect(selectExpr);
       // Parameters are represented as {2}, {3}, etc.
       // Braces in string literals are escaped and are represented as '{0}' and '{1}'
       var sqlTemplate = sqlStatement.ToString();
       var sql = FormatSql(sqlTemplate, commandParams);
       var objMaterializer = CompileObjectMaterializer(context);
       var outType = context.CurrentSelect.Reader.Body.Type;
       var resultListCreator = ReflectionHelper.GetCompiledGenericListCreator(outType);
       //check if we need to create implicit result set processor
       if (selectExpr.ResultsProcessor == null) {
     var returnsResultSet = typeof(IQueryable).IsAssignableFrom(cmdInfo.Lambda.Body.Type);
     if (!returnsResultSet)
       selectExpr.ResultsProcessor = QueryResultsProcessor.CreateFirstSingleLast("First", outType);
       }
       var sqlQuery = new TranslatedLinqCommand(sqlTemplate, sql, commandParams, command.Info.Flags,
           objMaterializer, selectExpr.ResultsProcessor, resultListCreator);
       return sqlQuery;
 }
Exemplo n.º 9
0
 private void CheckExternalValue(ExternalValueExpression extValue)
 {
 }