示例#1
0
        private static DbModificationCommandTree RebuildCommandTree(
            DbModificationCommandTree originalTree, Dictionary <DbSetClause, DbSetClause> clauseMappings)
        {
            if (clauseMappings.Count == 0)
            {
                return(originalTree);
            }

            DbModificationCommandTree result;

            Debug.Assert(
                originalTree.CommandTreeKind == DbCommandTreeKind.Insert || originalTree.CommandTreeKind == DbCommandTreeKind.Update,
                "Set clauses specified for a modification tree that is not an update or insert tree?");
            if (originalTree.CommandTreeKind
                == DbCommandTreeKind.Insert)
            {
                var insertTree = (DbInsertCommandTree)originalTree;
                result = new DbInsertCommandTree(
                    insertTree.MetadataWorkspace, insertTree.DataSpace,
                    insertTree.Target, new ReadOnlyCollection <DbModificationClause>(ReplaceClauses(insertTree.SetClauses, clauseMappings)), insertTree.Returning);
            }
            else
            {
                var updateTree = (DbUpdateCommandTree)originalTree;
                result = new DbUpdateCommandTree(
                    updateTree.MetadataWorkspace, updateTree.DataSpace,
                    updateTree.Target, updateTree.Predicate, new ReadOnlyCollection <DbModificationClause>(ReplaceClauses(updateTree.SetClauses, clauseMappings)),
                    updateTree.Returning);
            }

            return(result);
        }
    protected override SelectStatement GenerateReturningSql(DbModificationCommandTree tree, DbExpression returning)
    {      
      SelectStatement select = base.GenerateReturningSql(tree, returning);      

      ListFragment where = new ListFragment();

      EntitySetBase table = ((DbScanExpression)tree.Target.Expression).Target;
      bool foundIdentity = false;
      where.Append(" row_count() > 0");
      foreach (EdmMember keyMember in table.ElementType.KeyMembers)
      {
        SqlFragment value;
        if (!values.TryGetValue(keyMember, out value))
        {
          if (foundIdentity)
            throw new NotSupportedException();
          foundIdentity = true;
          PrimitiveTypeKind type = ((PrimitiveType)keyMember.TypeUsage.EdmType.BaseType).PrimitiveTypeKind;
          if ((type == PrimitiveTypeKind.Byte) || (type == PrimitiveTypeKind.SByte) ||
              (type == PrimitiveTypeKind.Int16) || (type == PrimitiveTypeKind.Int32) ||
              (type == PrimitiveTypeKind.Int64))
          {
            value = new LiteralFragment("last_insert_id()");
	  }
          else if (keyMember.TypeUsage.EdmType.BaseType.Name == "Guid")
            value = new LiteralFragment(string.Format("ANY(SELECT guid FROM tmpIdentity_{0})", (table as MetadataItem).MetadataProperties["Table"].Value));
        }
        where.Append(String.Format(" AND `{0}`=", keyMember));
        where.Append(value);
      }
      select.Where = where;      
      return select;
    }
示例#3
0
        // effects: try to find setter expression for the given member
        // requires: command tree must be an insert or update tree (since other DML trees hnabve
        private static bool TryGetSetterExpression(
            DbModificationCommandTree tree, EdmMember member, ModificationOperator op, out DbSetClause setter)
        {
            Debug.Assert(op == ModificationOperator.Insert || op == ModificationOperator.Update, "only inserts and updates have setters");
            IEnumerable <DbModificationClause> clauses;

            if (ModificationOperator.Insert == op)
            {
                clauses = ((DbInsertCommandTree)tree).SetClauses;
            }
            else
            {
                clauses = ((DbUpdateCommandTree)tree).SetClauses;
            }
            foreach (DbSetClause setClause in clauses)
            {
                // check if this is the correct setter
                if (((DbPropertyExpression)setClause.Property).Property.EdmEquals(member))
                {
                    setter = setClause;
                    return(true);
                }
            }

            // no match found
            setter = null;
            return(false);
        }
示例#4
0
        protected SelectStatement GenerateReturningSql(DbModificationCommandTree tree, DbExpression returning)
        {
            SelectStatement select = new SelectStatement();

            Debug.Assert(returning is DbNewInstanceExpression);
            VisitNewInstanceExpression(select, returning as DbNewInstanceExpression);

            select.From = (InputFragment)tree.Target.Expression.Accept(this);

            ListFragment where = new ListFragment();
            where.Append(" row_count() > 0");

            EntitySetBase table         = ((DbScanExpression)tree.Target.Expression).Target;
            bool          foundIdentity = false;

            foreach (EdmMember keyMember in table.ElementType.KeyMembers)
            {
                SqlFragment value;
                if (!values.TryGetValue(keyMember, out value))
                {
                    if (foundIdentity)
                    {
                        throw new NotSupportedException();
                    }
                    foundIdentity = true;
                    value         = new LiteralFragment("last_insert_id()");
                }
                where.Append(String.Format(" AND `{0}`=", keyMember));
                where.Append(value);
            }
            select.Where = where;
            return(select);
        }
示例#5
0
        /// <summary>
        ///     Generates SQL fragment returning server-generated values.
        ///     Requires: translator knows about member values so that we can figure out
        ///     how to construct the key predicate.
        ///     <code>Sample SQL:
        ///
        ///         select IdentityValue
        ///         from MyTable
        ///         where IdentityValue = @@identity
        ///
        ///         NOTE: not scope_identity() because we don't support it.</code>
        /// </summary>
        /// <param name="commandText"> Builder containing command text </param>
        /// <param name="tree"> Modification command tree </param>
        /// <param name="translator"> Translator used to produce DML SQL statement for the tree </param>
        /// <param name="returning"> Returning expression. If null, the method returns immediately without producing a SELECT statement. </param>
        private static void GenerateReturningSql(
            StringBuilder commandText, DbModificationCommandTree tree,
            ExpressionTranslator translator, DbExpression returning)
        {
            if (returning != null)
            {
                commandText.Append("select ");
                returning.Accept(translator);
                commandText.AppendLine();
                commandText.Append("from ");
                tree.Target.Expression.Accept(translator);
                commandText.AppendLine();
                commandText.Append("where ");
                var target  = ((DbScanExpression)tree.Target.Expression).Target;
                var flag    = false;
                var isFirst = true;
                foreach (var member in target.ElementType.KeyMembers)
                {
                    if (!isFirst)
                    {
                        commandText.Append(" and ");
                    }
                    else
                    {
                        isFirst = false;
                    }

                    commandText.Append(GenerateMemberTSql(member));
                    commandText.Append(" = ");
                    flag = HandleIdentity(commandText, translator, member, flag, target);
                }
            }
        }
示例#6
0
        /// <summary>
        /// Gets DB command definition encapsulating store logic for this command.
        /// </summary>
        private DbCommand CreateCommand(UpdateTranslator translator, Dictionary <int, object> identifierValues)
        {
            DbModificationCommandTree commandTree = m_modificationCommandTree;

            // check if any server gen identifiers need to be set
            if (null != m_inputIdentifiers)
            {
                Dictionary <DbSetClause, DbSetClause> modifiedClauses = new Dictionary <DbSetClause, DbSetClause>();
                for (int idx = 0; idx < m_inputIdentifiers.Count; idx++)
                {
                    KeyValuePair <int, DbSetClause> inputIdentifier = m_inputIdentifiers[idx];

                    object value;
                    if (identifierValues.TryGetValue(inputIdentifier.Key, out value))
                    {
                        // reset the value of the identifier
                        DbSetClause newClause = new DbSetClause(inputIdentifier.Value.Property, DbExpressionBuilder.Constant(value));
                        modifiedClauses[inputIdentifier.Value] = newClause;
                        m_inputIdentifiers[idx] = new KeyValuePair <int, DbSetClause>(inputIdentifier.Key, newClause);
                    }
                }
                commandTree = RebuildCommandTree(commandTree, modifiedClauses);
            }

            return(translator.CreateCommand(commandTree));
        }
示例#7
0
        internal DynamicUpdateCommand(TableChangeProcessor processor, UpdateTranslator translator, ModificationOperator op,
                                      PropagatorResult originalValues, PropagatorResult currentValues, DbModificationCommandTree tree,
                                      Dictionary <int, string> outputIdentifiers)
            : base(originalValues, currentValues)
        {
            m_processor = EntityUtil.CheckArgumentNull(processor, "processor");
            m_operator  = op;
            m_modificationCommandTree = EntityUtil.CheckArgumentNull(tree, "commandTree");
            m_outputIdentifiers       = outputIdentifiers; // may be null (not all commands have output identifiers)

            // initialize identifier information (supports lateral propagation of server gen values)
            if (ModificationOperator.Insert == op || ModificationOperator.Update == op)
            {
                const int capacity = 2; // "average" number of identifiers per row
                m_inputIdentifiers = new List <KeyValuePair <int, DbSetClause> >(capacity);

                foreach (KeyValuePair <EdmMember, PropagatorResult> member in
                         Helper.PairEnumerations(TypeHelpers.GetAllStructuralMembers(this.CurrentValues.StructuralType),
                                                 this.CurrentValues.GetMemberValues()))
                {
                    DbSetClause setter;
                    int         identifier = member.Value.Identifier;

                    if (PropagatorResult.NullIdentifier != identifier &&
                        TryGetSetterExpression(tree, member.Key, op, out setter)) // can find corresponding setter
                    {
                        foreach (int principal in translator.KeyManager.GetPrincipals(identifier))
                        {
                            m_inputIdentifiers.Add(new KeyValuePair <int, DbSetClause>(principal, setter));
                        }
                    }
                }
            }
        }
示例#8
0
        protected virtual SelectStatement GenerateReturningSql(DbModificationCommandTree tree, DbExpression returning)
        {
            SelectStatement select = base.GenerateReturningSql(tree, returning);

            ListFragment where = new ListFragment();

            EntitySetBase table         = ((DbScanExpression)tree.Target.Expression).Target;
            bool          foundIdentity = false;

            where.Append(" row_count() > 0");
            foreach (EdmMember keyMember in table.ElementType.KeyMembers)
            {
                SqlFragment value;
                if (!values.TryGetValue(keyMember, out value))
                {
                    if (foundIdentity)
                    {
                        throw new NotSupportedException();
                    }
                    foundIdentity = true;
                    if (keyMember.TypeUsage.EdmType.BaseType.Name.StartsWith("Int"))
                    {
                        value = new LiteralFragment("last_insert_id()");
                    }
                    else if (keyMember.TypeUsage.EdmType.BaseType.Name == "Guid")
                    {
                        value = new LiteralFragment(string.Format("ANY(SELECT guid FROM tmpIdentity_{0})", (table as MetadataItem).MetadataProperties["Table"].Value));
                    }
                }
                where.Append(String.Format(" AND `{0}`=", keyMember));
                where.Append(value);
            }
            select.Where = where;
            return(select);
        }
示例#9
0
 internal DynamicUpdateCommand(
     TableChangeProcessor processor,
     UpdateTranslator translator,
     ModificationOperator modificationOperator,
     PropagatorResult originalValues,
     PropagatorResult currentValues,
     DbModificationCommandTree tree,
     Dictionary <int, string> outputIdentifiers)
     : base(translator, originalValues, currentValues)
 {
     this._processor = processor;
     this._operator  = modificationOperator;
     this._modificationCommandTree = tree;
     this._outputIdentifiers       = outputIdentifiers;
     if (ModificationOperator.Insert != modificationOperator && modificationOperator != ModificationOperator.Update)
     {
         return;
     }
     this._inputIdentifiers = new List <KeyValuePair <int, DbSetClause> >(2);
     foreach (KeyValuePair <EdmMember, PropagatorResult> pairEnumeration in Helper.PairEnumerations <EdmMember, PropagatorResult>(TypeHelpers.GetAllStructuralMembers((EdmType)this.CurrentValues.StructuralType), (IEnumerable <PropagatorResult>) this.CurrentValues.GetMemberValues()))
     {
         int         identifier = pairEnumeration.Value.Identifier;
         DbSetClause setter;
         if (-1 != identifier && DynamicUpdateCommand.TryGetSetterExpression(tree, pairEnumeration.Key, modificationOperator, out setter))
         {
             foreach (int principal in translator.KeyManager.GetPrincipals(identifier))
             {
                 this._inputIdentifiers.Add(new KeyValuePair <int, DbSetClause>(principal, setter));
             }
         }
     }
 }
 internal ExpressionTranslator(StringBuilder commandText, DbModificationCommandTree commandTree, bool preserveMemberValues, EFOracleVersion version)
 {
     this._commandText  = commandText;
     this._commandTree  = commandTree;
     this._version      = version;
     this._parameters   = new List <OracleParameter>();
     this._memberValues = preserveMemberValues ? new Dictionary <EdmMember, OracleParameter>() : (Dictionary <EdmMember, OracleParameter>)null;
 }
示例#11
0
 private void DbScanExpressionThrowsTest(string functionName, DbModificationCommandTree commandTree)
 {
     Assert.Equal(
         Strings.Update_SqlEntitySetWithoutDmlFunctions("Binky", functionName, "ModificationFunctionMapping"),
         Assert.Throws <UpdateException>(
             () => new DmlSqlGenerator.ExpressionTranslator(new StringBuilder(), commandTree, true, SqlVersion.Sql10)
             .Visit(CreateMockScanExpression("I am defined.").Object)).Message);
 }
示例#12
0
 /// <summary>
 /// Initialize a new expression translator populating the given string builder
 /// with command text. Command text builder and command tree must not be null.
 /// </summary>
 /// <param name="commandText">Command text with which to populate commands</param>
 /// <param name="commandTree">Command tree generating SQL</param>
 /// <param name="preserveMemberValues">Indicates whether the translator should preserve
 /// member values while compiling t-SQL (only needed for server generation)</param>
 internal ExpressionTranslator(StringBuilder commandText, DbModificationCommandTree commandTree, bool preserveMemberValues)
 {
     Debug.Assert(null != commandText);
     Debug.Assert(null != commandTree);
     _commandText  = commandText;
     _commandTree  = commandTree;
     _parameters   = new List <DbParameter>();
     _memberValues = preserveMemberValues ? new Dictionary <EdmMember, DbParameter>() : null;
 }
示例#13
0
        /// <summary>
        /// Generates SQL fragment returning server-generated values.
        /// Requires: translator knows about member values so that we can figure out
        /// how to construct the key predicate.
        /// <code>
        /// Sample SQL:
        ///
        ///     select IdentityValue
        ///     from dbo.MyTable
        ///     where @@ROWCOUNT > 0 and IdentityValue = scope_identity()
        ///
        /// or
        ///
        ///     select TimestamptValue
        ///     from dbo.MyTable
        ///     where @@ROWCOUNT > 0 and Id = 1
        ///
        /// Note that we filter on rowcount to ensure no rows are returned if no rows were modified.
        /// </code>
        /// </summary>
        /// <param name="commandText">Builder containing command text</param>
        /// <param name="tree">Modification command tree</param>
        /// <param name="translator">Translator used to produce DML SQL statement
        /// for the tree</param>
        /// <param name="returning">Returning expression. If null, the method returns
        /// immediately without producing a SELECT statement.</param>
        private static void GenerateReturningSql(StringBuilder commandText, DbModificationCommandTree tree,
                                                 ExpressionTranslator translator, DbExpression returning)
        {
            // Nothing to do if there is no Returning expression
            if (null == returning)
            {
                return;
            }

            // select
            commandText.Append("SELECT ");
            returning.Accept(translator);
            commandText.AppendLine();

            // from
            commandText.Append("FROM ");
            tree.Target.Expression.Accept(translator);
            commandText.AppendLine();

            // where
#if USE_INTEROP_DLL && INTEROP_EXTENSION_FUNCTIONS
            commandText.Append("WHERE last_rows_affected() > 0");
#else
            commandText.Append("WHERE changes() > 0");
#endif
            EntitySetBase table    = ((DbScanExpression)tree.Target.Expression).Target;
            bool          identity = false;
            foreach (EdmMember keyMember in table.ElementType.KeyMembers)
            {
                commandText.Append(" AND ");
                commandText.Append(GenerateMemberTSql(keyMember));
                commandText.Append(" = ");

                // retrieve member value sql. the translator remembers member values
                // as it constructs the DML statement (which precedes the "returning"
                // SQL)
                DbParameter value;
                if (translator.MemberValues.TryGetValue(keyMember, out value))
                {
                    commandText.Append(value.ParameterName);
                    commandText.AppendLine(";");
                }
                else
                {
                    // if no value is registered for the key member, it means it is an identity
                    // which can be retrieved using the scope_identity() function
                    if (identity)
                    {
                        // there can be only one server generated key
                        throw new NotSupportedException(string.Format("Server generated keys are only supported for identity columns. More than one key column is marked as server generated in table '{0}'.", table.Name));
                    }
                    commandText.AppendLine("last_insert_rowid();");
                    identity = true;
                }
            }
        }
示例#14
0
            /// <summary>
            /// Initialize a new expression translator populating the given string builder
            /// with command text. Command text builder and command tree must not be null.
            /// </summary>
            /// <param name="commandText">Command text with which to populate commands</param>
            /// <param name="commandTree">Command tree generating SQL</param>
            /// <param name="preserveMemberValues">Indicates whether the translator should preserve
            /// member values while compiling sql expression</param>
            /// <param name="insertParametersValuesInSql">if set to <c>true</c> parameters values are inserted directly in SQL statement.</param>
            internal ExpressionTranslator(StringBuilder commandText, DbModificationCommandTree commandTree, bool preserveMemberValues, bool insertParametersValuesInSql)
            {
                Debug.Assert(commandText != null);
                Debug.Assert(commandTree != null);

                _commandText  = commandText;
                _parameters   = new List <DbParameter>();
                _memberValues = preserveMemberValues ? new Dictionary <EdmMember, DbParameter>() : null;
                _insertParametersValuesInSql = insertParametersValuesInSql;
            }
    protected override SelectStatement GenerateReturningSql(DbModificationCommandTree tree, DbExpression returning)
    {
      SelectStatement select = base.GenerateReturningSql(tree, returning);
      ListFragment where = new ListFragment();
      where.Append(" row_count() > 0 and ");
      where.Append( ((DbUpdateCommandTree)tree).Predicate.Accept(this) );
      select.Where = where;

      return select;
    }
示例#16
0
        protected override SelectStatement GenerateReturningSql(DbModificationCommandTree tree, DbExpression returning)
        {
            SelectStatement select = base.GenerateReturningSql(tree, returning);

            ListFragment where = new ListFragment();
            where.Append(" row_count() > 0 and ");
            where.Append(((System.Data.Common.CommandTrees.DbUpdateCommandTree)tree).Predicate.Accept(this));
            select.Where = where;

            return(select);
        }
        /// <summary>
        /// Initialize a new expression translator populating the given string builder
        /// with command text. Command text builder and command tree must not be null.
        /// </summary>
        /// <param name="commandText">Command text with which to populate commands</param>
        /// <param name="commandTree">Command tree generating SQL</param>
        /// <param name="preserveMemberValues">Indicates whether the translator should preserve
        /// member values while compiling t-SQL (only needed for server generation)</param>
        internal ExpressionTranslator(
            StringBuilder commandText,
            DbModificationCommandTree commandTree,
            bool preserveMemberValues)
        {
            Debug.Assert(null != commandText);
            Debug.Assert(null != commandTree);

            this.commandText = commandText;
            this.commandTree = commandTree;
            this.parameters = new List<DbParameter>();
            this.memberValues = preserveMemberValues ? new Dictionary<EdmMember, List<DbParameter>>() : null;
        }
示例#18
0
        protected virtual SelectStatement GenerateReturningSql(DbModificationCommandTree tree, DbExpression returning)
        {
            SelectStatement select = new SelectStatement(this);

            Debug.Assert(returning is DbNewInstanceExpression);
            VisitNewInstanceExpression(select, returning as DbNewInstanceExpression);

            select.From = (InputFragment)tree.Target.Expression.Accept(this);

            ListFragment where = new ListFragment();
            select.Where       = where;
            return(select);
        }
示例#19
0
 /// <summary>
 ///     Initialize a new expression translator populating the given string builder
 ///     with command text. Command text builder and command tree must not be null.
 /// </summary>
 /// <param name="commandText"> Command text with which to populate commands </param>
 /// <param name="commandTree"> Command tree generating SQL </param>
 /// <param name="preserveMemberValues"> Indicates whether the translator should preserve member values while compiling t-SQL (only needed for server generation) </param>
 internal ExpressionTranslator(
     StringBuilder commandText, DbModificationCommandTree commandTree,
     bool preserveMemberValues, bool isLocalProvider)
 {
     DebugCheck.NotNull(commandText);
     DebugCheck.NotNull(commandTree);
     _commandText  = commandText;
     _commandTree  = commandTree;
     _parameters   = new List <DbParameter>();
     _memberValues = preserveMemberValues
                         ? new Dictionary <EdmMember, DbParameter>()
                         : null;
     _isLocalProvider = isLocalProvider;
 }
        public static ITable GetTable(
            DbModificationCommandTree commandTree,
            DbContainer container)
        {
            DbScanExpression source = commandTree.Target.Expression as DbScanExpression;

            if (source == null)
            {
                throw new NotSupportedException(
                          "The type of the Target property is not DbScanExpression");
            }

            return(container.Internal.GetTable(source.Target.GetTableName()));
        }
示例#21
0
 /// <summary>
 ///     Initialize a new expression translator populating the given string builder
 ///     with command text. Command text builder and command tree must not be null.
 /// </summary>
 /// <param name="commandText"> Command text with which to populate commands </param>
 /// <param name="commandTree"> Command tree generating SQL </param>
 /// <param name="preserveMemberValues"> Indicates whether the translator should preserve member values while compiling t-SQL (only needed for server generation) </param>
 internal ExpressionTranslator(
     StringBuilder commandText, DbModificationCommandTree commandTree,
     bool preserveMemberValues, SqlVersion version)
 {
     DebugCheck.NotNull(commandText);
     DebugCheck.NotNull(commandTree);
     _commandText  = commandText;
     _commandTree  = commandTree;
     _version      = version;
     _parameters   = new List <SqlParameter>();
     _memberValues = preserveMemberValues
                         ? new Dictionary <EdmMember, SqlParameter>()
                         : null;
 }
        public static ITable GetTable(
            DbModificationCommandTree commandTree, 
            DbContainer container)
        {
            DbScanExpression source = commandTree.Target.Expression as DbScanExpression;

            if (source == null)
            {
                throw new NotSupportedException(
                    "The type of the Target property is not DbScanExpression");
            }

            return container.Internal.GetTable(source.Target.GetTableName());
        }
示例#23
0
        /// <summary>
        ///     Generates SQL fragment returning server-generated values.
        ///     Requires: translator knows about member values so that we can figure out
        ///     how to construct the key predicate.
        ///     <code>Sample SQL:
        ///
        ///         select IdentityValue
        ///         from MyTable
        ///         where IdentityValue = @@identity
        ///
        ///         NOTE: not scope_identity() because we don't support it.</code>
        /// </summary>
        /// <param name="commandText"> Builder containing command text </param>
        /// <param name="tree"> Modification command tree </param>
        /// <param name="translator"> Translator used to produce DML SQL statement for the tree </param>
        /// <param name="returning"> Returning expression. If null, the method returns immediately without producing a SELECT statement. </param>
        private static void GenerateReturningSql(
            StringBuilder commandText, DbModificationCommandTree tree,
            ExpressionTranslator translator, DbExpression returning)
        {
            if (returning != null)
            {
                commandText.Append("select ");
                returning.Accept(translator);
                commandText.AppendLine();
                commandText.Append("from ");
                tree.Target.Expression.Accept(translator);
                commandText.AppendLine();
                commandText.Append("where ");
                var target  = ((DbScanExpression)tree.Target.Expression).Target;
                var flag    = false;
                var isFirst = true;
                foreach (var member in target.ElementType.KeyMembers)
                {
                    DbParameter parameter;
                    if (!isFirst)
                    {
                        commandText.Append(" and ");
                    }
                    else
                    {
                        isFirst = false;
                    }

                    commandText.Append(GenerateMemberTSql(member));
                    commandText.Append(" = ");
                    if (translator.MemberValues.TryGetValue(member, out parameter))
                    {
                        commandText.Append(parameter.ParameterName);
                    }
                    else
                    {
                        if (flag)
                        {
                            throw ADP1.NotSupported(ADP1.Update_NotSupportedServerGenKey(target.Name));
                        }
                        if (!IsValidIdentityColumnType(member.TypeUsage))
                        {
                            throw ADP1.InvalidOperation(ADP1.Update_NotSupportedIdentityType(member.Name, member.TypeUsage.ToString()));
                        }
                        commandText.Append("@@IDENTITY");
                        flag = true;
                    }
                }
            }
        }
示例#24
0
        /// <summary>
        /// Initialize a new expression translator populating the given string builder
        /// with command text. Command text builder and command tree must not be null.
        /// </summary>
        /// <param name="commandText">Command text with which to populate commands</param>
        /// <param name="commandTree">Command tree generating SQL</param>
        /// <param name="preserveMemberValues">Indicates whether the translator should preserve
        /// member values while compiling t-SQL (only needed for server generation)</param>
        internal ExpressionTranslator(
            StringBuilder commandText,
            DbModificationCommandTree commandTree,
            bool preserveMemberValues,
            bool generateParameters)
        {
            Debug.Assert(null != commandText);
            Debug.Assert(null != commandTree);

            this.commandText        = commandText;
            this.commandTree        = commandTree;
            this.parameters         = new List <DbParameter>();
            this.memberValues       = preserveMemberValues ? new Dictionary <EdmMember, List <DbParameter> >() : null;
            this.generateParameters = generateParameters;
        }
 internal ExpressionTranslator(
     SqlStringBuilder commandText,
     DbModificationCommandTree commandTree,
     bool preserveMemberValues,
     SqlGenerator sqlGenerator,
     ICollection <EdmProperty> localVariableBindings = null,
     bool createParameters = true)
 {
     this._commandText           = commandText;
     this._commandTree           = commandTree;
     this._sqlGenerator          = sqlGenerator;
     this._localVariableBindings = localVariableBindings;
     this._parameters            = new List <SqlParameter>();
     this._memberValues          = preserveMemberValues ? new Dictionary <EdmMember, SqlParameter>() : (Dictionary <EdmMember, SqlParameter>)null;
     this._createParameters      = createParameters;
 }
示例#26
0
 private static bool TryGetSetterExpression(
     DbModificationCommandTree tree,
     EdmMember member,
     ModificationOperator op,
     out DbSetClause setter)
 {
     foreach (DbSetClause dbSetClause in ModificationOperator.Insert != op ? (IEnumerable <DbModificationClause>)((DbUpdateCommandTree)tree).SetClauses : (IEnumerable <DbModificationClause>)((DbInsertCommandTree)tree).SetClauses)
     {
         if (((DbPropertyExpression)dbSetClause.Property).Property.EdmEquals((MetadataItem)member))
         {
             setter = dbSetClause;
             return(true);
         }
     }
     setter = (DbSetClause)null;
     return(false);
 }
示例#27
0
        private DbModificationCommandTree ConvertInternalByType(DbModificationCommandTree commandTree)
        {
            if (commandTree is DbInsertCommandTree ins)
            {
                return(ConvertInternal(ins));
            }
            if (commandTree is DbUpdateCommandTree upd)
            {
                return(ConvertInternal(upd));
            }
            if (commandTree is DbDeleteCommandTree del)
            {
                return(ConvertInternal(del));
            }

            throw new ArgumentException("Unsupported command tree type", nameof(commandTree));
        }
        public static Expression GetEnumeratorExpression(
            DbExpression predicate,
            DbModificationCommandTree commandTree,
            DbContainer container,
            out ITable table)
        {
            TransformVisitor visitor = new TransformVisitor(container.TypeConverter);

            visitor.TableProvider = container;

            // Get the source expression
            ConstantExpression source =
                visitor.Visit(commandTree.Target.Expression) as ConstantExpression;

            // This should be a constant expression
            if (source == null)
            {
                throw new InvalidOperationException();
            }

            table = source.Value as ITable;

            // Get the the type of the elements of the table
            Type elementType = TypeHelper.GetElementType(source.Type);

            // Create context
            ParameterExpression context = Expression.Parameter(elementType, "context");

            using (visitor.CreateVariable(context, commandTree.Target.VariableName))
            {
                // Create the predicate expression
                LambdaExpression predicateExpression =
                    Expression.Lambda(
                        visitor.Visit(predicate),
                        context);

                // Create Where expression
                LinqMethodExpressionBuilder queryMethodBuilder =
                    new LinqMethodExpressionBuilder();

                return(queryMethodBuilder.Where(source, predicateExpression));
            }
        }
示例#29
0
            /// <summary>
            /// Initialize a new expression translator populating the given string builder
            /// with command text. Command text builder and command tree must not be null.
            /// </summary>
            /// <param name="commandText">Command text with which to populate commands</param>
            /// <param name="commandTree">Command tree generating SQL</param>
            /// <param name="preserveMemberValues">Indicates whether the translator should preserve
            /// member values while compiling t-SQL (only needed for server generation)</param>
            /// <param name="kind"></param>
            /// <param name="createParameters">Create Parameters (true) or literals</param>
            internal ExpressionTranslator(
                StringBuilder commandText,
                DbModificationCommandTree commandTree,
                bool preserveMemberValues,
                SqlGenerator sqlGenerator,
                string kind,
                bool createParameters = true)
            {
                Debug.Assert(null != commandText);
                Debug.Assert(null != commandTree);
                _kind         = kind;
                _commandText  = commandText;
                _commandTree  = commandTree;
                _sqlGenerator = sqlGenerator;
                _parameters   = new List <DbParameter>();
                _memberValues = preserveMemberValues ? new Dictionary <EdmMember, DbParameter>() :
                                null;

                _createParameters = createParameters;
            }
示例#30
0
            /// <summary>
            ///     Initialize a new expression translator populating the given string builder
            ///     with command text. Command text builder and command tree must not be null.
            /// </summary>
            /// <param name="commandText"> Command text with which to populate commands </param>
            /// <param name="commandTree"> Command tree generating SQL </param>
            /// <param name="preserveMemberValues"> Indicates whether the translator should preserve member values while compiling t-SQL (only needed for server generation) </param>
            internal ExpressionTranslator(
                StringBuilder commandText,
                DbModificationCommandTree commandTree,
                bool preserveMemberValues,
                SqlGenerator sqlGenerator,
                ICollection <EdmProperty> localVariableBindings = null)
            {
                DebugCheck.NotNull(commandText);
                DebugCheck.NotNull(commandTree);

                _commandText           = commandText;
                _commandTree           = commandTree;
                _sqlGenerator          = sqlGenerator;
                _localVariableBindings = localVariableBindings;

                _parameters = new List <SqlParameter>();

                _memberValues = preserveMemberValues
                                    ? new Dictionary <EdmMember, SqlParameter>()
                                    : null;
            }
示例#31
0
        protected virtual DbCommand CreateCommand(Dictionary <int, object> identifierValues)
        {
            DbModificationCommandTree modificationCommandTree = this._modificationCommandTree;

            if (this._inputIdentifiers != null)
            {
                Dictionary <DbSetClause, DbSetClause> clauseMappings = new Dictionary <DbSetClause, DbSetClause>();
                for (int index = 0; index < this._inputIdentifiers.Count; ++index)
                {
                    KeyValuePair <int, DbSetClause> inputIdentifier = this._inputIdentifiers[index];
                    object obj;
                    if (identifierValues.TryGetValue(inputIdentifier.Key, out obj))
                    {
                        DbSetClause dbSetClause = new DbSetClause(inputIdentifier.Value.Property, (DbExpression)DbExpressionBuilder.Constant(obj));
                        clauseMappings[inputIdentifier.Value] = dbSetClause;
                        this._inputIdentifiers[index]         = new KeyValuePair <int, DbSetClause>(inputIdentifier.Key, dbSetClause);
                    }
                }
                modificationCommandTree = DynamicUpdateCommand.RebuildCommandTree(modificationCommandTree, clauseMappings);
            }
            return(this.Translator.CreateCommand(modificationCommandTree));
        }
示例#32
0
        private static DbModificationCommandTree RebuildCommandTree(
            DbModificationCommandTree originalTree,
            Dictionary <DbSetClause, DbSetClause> clauseMappings)
        {
            if (clauseMappings.Count == 0)
            {
                return(originalTree);
            }
            DbModificationCommandTree modificationCommandTree;

            if (originalTree.CommandTreeKind == DbCommandTreeKind.Insert)
            {
                DbInsertCommandTree insertCommandTree = (DbInsertCommandTree)originalTree;
                modificationCommandTree = (DbModificationCommandTree) new DbInsertCommandTree(insertCommandTree.MetadataWorkspace, insertCommandTree.DataSpace, insertCommandTree.Target, new ReadOnlyCollection <DbModificationClause>((IList <DbModificationClause>)DynamicUpdateCommand.ReplaceClauses(insertCommandTree.SetClauses, clauseMappings)), insertCommandTree.Returning);
            }
            else
            {
                DbUpdateCommandTree updateCommandTree = (DbUpdateCommandTree)originalTree;
                modificationCommandTree = (DbModificationCommandTree) new DbUpdateCommandTree(updateCommandTree.MetadataWorkspace, updateCommandTree.DataSpace, updateCommandTree.Target, updateCommandTree.Predicate, new ReadOnlyCollection <DbModificationClause>((IList <DbModificationClause>)DynamicUpdateCommand.ReplaceClauses(updateCommandTree.SetClauses, clauseMappings)), updateCommandTree.Returning);
            }
            return(modificationCommandTree);
        }
        protected override SelectStatement GenerateReturningSql(DbModificationCommandTree tree, DbExpression returning)
        {
            SelectStatement select = base.GenerateReturningSql(tree, returning);
              ListFragment where = new ListFragment();
              where.Append(" row_count() > 0 and ");
            #if EF6
              where.Append( ((System.Data.Entity.Core.Common.CommandTrees.DbUpdateCommandTree)tree).Predicate.Accept(this) );
            #else
              where.Append( ((System.Data.Common.CommandTrees.DbUpdateCommandTree)tree).Predicate.Accept(this) );
            #endif
              select.Where = where;

              return select;
        }
示例#34
0
        /// <summary>
        ///     Generates SQL fragment returning server-generated values.
        ///     Requires: translator knows about member values so that we can figure out
        ///     how to construct the key predicate.
        ///     <code>Sample SQL:
        ///
        ///         select IdentityValue
        ///         from dbo.MyTable
        ///         where @@ROWCOUNT > 0 and IdentityValue = scope_identity()
        ///
        ///         or
        ///
        ///         select TimestampValue
        ///         from dbo.MyTable
        ///         where @@ROWCOUNT > 0 and Id = 1
        ///
        ///         Note that we filter on rowcount to ensure no rows are returned if no rows were modified.
        ///
        ///         On SQL Server 2005 and up, we have an additional syntax used for non integer return types:
        ///
        ///         declare @generatedValues table(ID uniqueidentifier)
        ///         insert dbo.MyTable
        ///         output ID into @generated_values
        ///         values (...);
        ///         select ID
        ///         from @generatedValues as g join dbo.MyTable as t on g.ID = t.ID
        ///         where @@ROWCOUNT > 0;</code>
        /// </summary>
        /// <param name="commandText"> Builder containing command text </param>
        /// <param name="tree"> Modification command tree </param>
        /// <param name="tableType"> Type of table. </param>
        /// <param name="translator"> Translator used to produce DML SQL statement for the tree </param>
        /// <param name="returning"> Returning expression. If null, the method returns immediately without producing a SELECT statement. </param>
        internal static void GenerateReturningSql(
            SqlStringBuilder commandText,
            DbModificationCommandTree tree,
            EntityType tableType,
            ExpressionTranslator translator,
            DbExpression returning,
            bool useGeneratedValuesVariable)
        {
            // Nothing to do if there is no Returning expression
            if (null == returning)
            {
                return;
            }

            // select
            commandText.AppendKeyword("select ");
            if (useGeneratedValuesVariable)
            {
                translator.PropertyAlias = "t";
            }
            returning.Accept(translator);
            if (useGeneratedValuesVariable)
            {
                translator.PropertyAlias = null;
            }
            commandText.AppendLine();

            if (useGeneratedValuesVariable)
            {
                // from @generated_keys
                commandText.AppendKeyword("from ");
                commandText.Append(GeneratedValuesVariableName);
                commandText.AppendKeyword(" as ");
                commandText.Append("g");
                commandText.AppendKeyword(" join ");
                tree.Target.Expression.Accept(translator);
                commandText.AppendKeyword(" as ");
                commandText.Append("t");
                commandText.AppendKeyword(" on ");
                var separator = string.Empty;
                foreach (var keyMember in tableType.KeyMembers)
                {
                    commandText.AppendKeyword(separator);
                    separator = " and ";
                    commandText.Append("g.");
                    var memberTSql = GenerateMemberTSql(keyMember);
                    commandText.Append(memberTSql);
                    commandText.Append(" = t.");
                    commandText.Append(memberTSql);
                }
                commandText.AppendLine();
                commandText.AppendKeyword("where @@ROWCOUNT > 0");
            }
            else
            {
                // from
                commandText.AppendKeyword("from ");
                tree.Target.Expression.Accept(translator);
                commandText.AppendLine();

                // where
                commandText.AppendKeyword("where @@ROWCOUNT > 0");
                var table    = ((DbScanExpression)tree.Target.Expression).Target;
                var identity = false;
                foreach (var keyMember in table.ElementType.KeyMembers)
                {
                    commandText.AppendKeyword(" and ");
                    commandText.Append(GenerateMemberTSql(keyMember));
                    commandText.Append(" = ");

                    // retrieve member value sql. the translator remembers member values
                    // as it constructs the DML statement (which precedes the "returning"
                    // SQL)
                    SqlParameter value;
                    if (translator.MemberValues.TryGetValue(keyMember, out value))
                    {
                        commandText.Append(value.ParameterName);
                    }
                    else
                    {
                        // if no value is registered for the key member, it means it is an identity
                        // which can be retrieved using the scope_identity() function
                        if (identity)
                        {
                            // there can be only one server generated key
                            throw new NotSupportedException(Strings.Update_NotSupportedServerGenKey(table.Name));
                        }

                        if (!IsValidScopeIdentityColumnType(keyMember.TypeUsage))
                        {
                            throw new InvalidOperationException(
                                      Strings.Update_NotSupportedIdentityType(
                                          keyMember.Name, keyMember.TypeUsage.ToString()));
                        }

                        commandText.Append("scope_identity()");
                        identity = true;
                    }
                }
            }
        }
		/// <summary>
		/// Generates SQL fragment returning server-generated values.
		/// Requires: translator knows about member values so that we can figure out
		/// how to construct the key predicate.
		/// <code>
		/// Sample SQL:
		///
		///     select IdentityValue
		///     from dbo.MyTable
		///     where @@ROWCOUNT > 0 and IdentityValue = scope_identity()
		///
		/// or
		///
		///     select TimestamptValue
		///     from dbo.MyTable
		///     where @@ROWCOUNT > 0 and Id = 1
		///
		/// Note that we filter on rowcount to ensure no rows are returned if no rows were modified.
		/// </code>
		/// </summary>
		/// <param name="commandText">Builder containing command text</param>
		/// <param name="tree">Modification command tree</param>
		/// <param name="translator">Translator used to produce DML SQL statement
		/// for the tree</param>
		/// <param name="returning">Returning expression. If null, the method returns
		/// immediately without producing a SELECT statement.</param>
		private static void GenerateReturningSql(
			StringBuilder commandText,
			DbModificationCommandTree tree,
			ExpressionTranslator translator,
			DbExpression returning)
		{
			// Nothing to do if there is no Returning expression
			if (returning == null)
			{
				return;
			}

			EntitySetBase table = ((DbScanExpression)tree.Target.Expression).Target;
			IEnumerable<EdmMember> columnsToFetch =
			table.ElementType.Members
				.Where(m => MetadataHelpers.IsStoreGenerated(m))
				.Except((!(tree is DbInsertCommandTree) ? table.ElementType.KeyMembers : Enumerable.Empty<EdmMember>()));

			StringBuilder startBlock = new StringBuilder();
			string separator = string.Empty;

			startBlock.Append("EXECUTE BLOCK ");
			if (translator.Parameters.Any())
			{
				startBlock.AppendLine("(");
				separator = string.Empty;
				foreach (FbParameter param in translator.Parameters)
				{
					startBlock.Append(separator);
					startBlock.Append(param.ParameterName.Replace("@", string.Empty));
					startBlock.Append(" ");
					EdmMember member = translator.MemberValues.First(m => m.Value.Contains(param)).Key;
					startBlock.Append(SqlGenerator.GetSqlPrimitiveType(member.TypeUsage));
					if (param.FbDbType == FbDbType.VarChar || param.FbDbType == FbDbType.Char)
						startBlock.Append(" CHARACTER SET UTF8");
					startBlock.Append(" = ");
					startBlock.Append(param.ParameterName);

					separator = ", ";
				}
				startBlock.AppendLine();
				startBlock.Append(") ");
			}

			startBlock.AppendLine("RETURNS (");
			separator = string.Empty;
			foreach (EdmMember m in columnsToFetch)
			{
				startBlock.Append(separator);
				startBlock.Append(GenerateMemberSql(m));
				startBlock.Append(" ");
				startBlock.Append(SqlGenerator.GetSqlPrimitiveType(m.TypeUsage));

				separator = ", ";
			}
			startBlock.AppendLine(")");
			startBlock.AppendLine("AS BEGIN");

			string newCommand = ChangeParamsToPSQLParams(commandText.ToString(), translator.Parameters.Select(p => p.ParameterName).ToArray());
			commandText.Remove(0, commandText.Length);
			commandText.Insert(0, newCommand);
			commandText.Insert(0, startBlock.ToString());

			commandText.Append("RETURNING ");
			separator = string.Empty;
			foreach (EdmMember m in columnsToFetch)
			{
				commandText.Append(separator);
				commandText.Append(GenerateMemberSql(m));

				separator = ", ";
			}
			commandText.Append(" INTO ");
			separator = string.Empty;
			foreach (EdmMember m in columnsToFetch)
			{
				commandText.Append(separator);
				commandText.Append(":" + GenerateMemberSql(m));

				separator = ", ";
			}

			commandText.AppendLine(";");
			commandText.AppendLine("SUSPEND;");
			commandText.AppendLine("END");
		}
        private static void GenerateReturningSql(StringBuilder commandText, DbModificationCommandTree tree, DmlSqlGenerator.ExpressionTranslator translator, DbExpression returning, EFOracleProviderManifest providerManifest, EFOracleVersion sqlVersion, bool isUpdate)
        {
            if (returning == null)
            {
                return;
            }
            EntitySetBase target        = ((DbScanExpression)tree.Target.Expression).Target;
            StringBuilder stringBuilder = new StringBuilder(50);

            stringBuilder.Append("declare\n");
            Dictionary <EdmMember, string> dictionary = new Dictionary <EdmMember, string>();

            foreach (EdmMember member in target.ElementType.Members)
            {
                ReadOnlyMetadataCollection <Facet> facets = ((TypeUsage)member.MetadataProperties["TypeUsage"].Value).Facets;
                string empty = string.Empty;
                if (facets.Contains("StoreGeneratedPattern"))
                {
                    string str = facets["StoreGeneratedPattern"].Value.ToString();
                    if (!string.IsNullOrEmpty(str))
                    {
                        if (isUpdate && str.ToUpperInvariant() == "COMPUTED")
                        {
                            dictionary[member] = str;
                        }
                        else if (!isUpdate && (str.ToUpperInvariant() == "COMPUTED" || str.ToUpperInvariant() == "IDENTITY"))
                        {
                            dictionary[member] = str;
                        }
                    }
                }
                if (dictionary.ContainsKey(member))
                {
                    stringBuilder.Append(DmlSqlGenerator.GenerateMemberTSql(member));
                    stringBuilder.Append(" ");
                    stringBuilder.Append(SqlGenerator.GetSqlPrimitiveType((DbProviderManifest)providerManifest, sqlVersion, member.TypeUsage));
                    stringBuilder.Append(";\n");
                }
            }
            stringBuilder.Append("begin\n");
            commandText.Insert(0, stringBuilder.ToString());
            OracleParameter parameter = translator.CreateParameter(OracleDbType.RefCursor, ParameterDirection.Output);

            commandText.Append("returning\n");
            string str1 = string.Empty;

            foreach (EdmMember member in target.ElementType.Members)
            {
                if (dictionary.ContainsKey(member))
                {
                    commandText.Append(str1);
                    commandText.Append(DmlSqlGenerator.GenerateMemberTSql(member));
                    str1 = ", ";
                }
            }
            commandText.Append(" into\n");
            string str2 = string.Empty;

            foreach (EdmMember member in target.ElementType.Members)
            {
                if (dictionary.ContainsKey(member))
                {
                    commandText.Append(str2);
                    commandText.Append(DmlSqlGenerator.GenerateMemberTSql(member));
                    str2 = ", ";
                }
            }
            commandText.Append(";\n");
            commandText.Append("open ");
            commandText.Append(parameter.ParameterName);
            commandText.Append(" for select\n");
            string str3 = string.Empty;

            foreach (EdmMember member in target.ElementType.Members)
            {
                if (dictionary.ContainsKey(member))
                {
                    commandText.Append(str3);
                    commandText.Append(DmlSqlGenerator.GenerateMemberTSql(member));
                    commandText.Append(" as ");
                    commandText.Append(DmlSqlGenerator.GenerateMemberTSql(member));
                    str3 = ", ";
                }
            }
            commandText.Append(" from dual;\n");
            commandText.Append("end;");
        }
    /// <summary>
    /// Generates SQL fragment returning server-generated values.
    /// Requires: translator knows about member values so that we can figure out
    /// how to construct the key predicate.
    /// <code>
    /// Sample SQL:
    ///     
    ///     select IdentityValue
    ///     from dbo.MyTable
    ///     where @@ROWCOUNT > 0 and IdentityValue = scope_identity()
    /// 
    /// or
    /// 
    ///     select TimestamptValue
    ///     from dbo.MyTable
    ///     where @@ROWCOUNT > 0 and Id = 1
    /// 
    /// Note that we filter on rowcount to ensure no rows are returned if no rows were modified.
    /// </code>
    /// </summary>
    /// <param name="commandText">Builder containing command text</param>
    /// <param name="tree">Modification command tree</param>
    /// <param name="translator">Translator used to produce DML SQL statement
    /// for the tree</param>
    /// <param name="returning">Returning expression. If null, the method returns
    /// immediately without producing a SELECT statement.</param>
    private static void GenerateReturningSql(StringBuilder commandText, DbModificationCommandTree tree,
        ExpressionTranslator translator, DbExpression returning)
    {
      // Nothing to do if there is no Returning expression
      if (null == returning) { return; }

      // select
      commandText.Append("SELECT ");
      returning.Accept(translator);
      commandText.AppendLine();

      // from
      commandText.Append("FROM ");
      tree.Target.Expression.Accept(translator);
      commandText.AppendLine();

      // where
#if USE_INTEROP_DLL && INTEROP_EXTENSION_FUNCTIONS
      commandText.Append("WHERE last_rows_affected() > 0");
#else
      commandText.Append("WHERE changes() > 0");
#endif
      EntitySetBase table = ((DbScanExpression)tree.Target.Expression).Target;
      bool identity = false;
      foreach (EdmMember keyMember in table.ElementType.KeyMembers)
      {
        commandText.Append(" AND ");
        commandText.Append(GenerateMemberTSql(keyMember));
        commandText.Append(" = ");

        // retrieve member value sql. the translator remembers member values
        // as it constructs the DML statement (which precedes the "returning"
        // SQL)
        DbParameter value;
        if (translator.MemberValues.TryGetValue(keyMember, out value))
        {
          commandText.Append(value.ParameterName);
          commandText.AppendLine(";");
        }
        else
        {
          // if no value is registered for the key member, it means it is an identity
          // which can be retrieved using the scope_identity() function
          if (identity)
          {
            // there can be only one server generated key
            throw new NotSupportedException(string.Format("Server generated keys are only supported for identity columns. More than one key column is marked as server generated in table '{0}'.", table.Name));
          }
          commandText.AppendLine("last_insert_rowid();");
          identity = true;
        }
      }
    }
 /// <summary>
 /// Initialize a new expression translator populating the given string builder
 /// with command text. Command text builder and command tree must not be null.
 /// </summary>
 /// <param name="commandText">Command text with which to populate commands</param>
 /// <param name="commandTree">Command tree generating SQL</param>
 /// <param name="preserveMemberValues">Indicates whether the translator should preserve
 /// member values while compiling t-SQL (only needed for server generation)</param>
 /// <param name="kind"></param>
 internal ExpressionTranslator(StringBuilder commandText, DbModificationCommandTree commandTree,
     bool preserveMemberValues, string kind)
 {
   Debug.Assert(null != commandText);
   Debug.Assert(null != commandTree);
   _kind = kind;
   _commandText = commandText;
   _commandTree = commandTree;
   _parameters = new List<DbParameter>();
   _memberValues = preserveMemberValues ? new Dictionary<EdmMember, DbParameter>() :
       null;
 }
示例#39
0
    /// <summary>
    /// Generates SQL fragment returning server-generated values.
    /// Requires: translator knows about member values so that we can figure out
    /// how to construct the key predicate.
    /// <code>
    /// Sample SQL:
    ///     
    ///     select IdentityValue
    ///     from dbo.MyTable
    ///     where @@ROWCOUNT > 0 and IdentityValue = scope_identity()
    /// 
    /// or
    /// 
    ///     select TimestamptValue
    ///     from dbo.MyTable
    ///     where @@ROWCOUNT > 0 and Id = 1
    /// 
    /// Note that we filter on rowcount to ensure no rows are returned if no rows were modified.
    /// </code>
    /// </summary>
    /// <param name="commandText">Builder containing command text</param>
    /// <param name="tree">Modification command tree</param>
    /// <param name="translator">Translator used to produce DML SQL statement
    /// for the tree</param>
    /// <param name="returning">Returning expression. If null, the method returns
    /// immediately without producing a SELECT statement.</param>
    /// <param name="wasInsert">
    /// Non-zero if this method is being called as part of processing an INSERT;
    /// otherwise (e.g. UPDATE), zero.
    /// </param>
    private static void GenerateReturningSql(StringBuilder commandText, DbModificationCommandTree tree,
        ExpressionTranslator translator, DbExpression returning, bool wasInsert)
    {
      // Nothing to do if there is no Returning expression
      if (null == returning) { return; }

      // select
      commandText.Append("SELECT ");
      returning.Accept(translator);
      commandText.AppendLine();

      // from
      commandText.Append("FROM ");
      tree.Target.Expression.Accept(translator);
      commandText.AppendLine();

      // where
#if USE_INTEROP_DLL && INTEROP_EXTENSION_FUNCTIONS
      commandText.Append("WHERE last_rows_affected() > 0");
#else
      commandText.Append("WHERE changes() > 0");
#endif

      EntitySetBase table = ((DbScanExpression)tree.Target.Expression).Target;
      ReadOnlyMetadataCollection<EdmMember> keyMembers;
      EdmMember primaryKeyMember;
      EdmMember missingKeyMember;

      // Model Types can be (at the time of this implementation):
      //      Binary, Boolean, Byte, DateTime, Decimal, Double, Guid, Int16,
      //      Int32, Int64,Single, String
      if (IsIntegerPrimaryKey(table, out keyMembers, out primaryKeyMember))
      {
          //
          // NOTE: This must be an INTEGER PRIMARY KEY (i.e. "rowid") table.
          //
          commandText.Append(" AND ");
          commandText.Append(GenerateMemberTSql(primaryKeyMember));
          commandText.Append(" = ");

          DbParameter value;

          if (translator.MemberValues.TryGetValue(primaryKeyMember, out value))
          {
              //
              // NOTE: Use the integer primary key value that was specified as
              //       part the associated INSERT/UPDATE statement.
              //
              commandText.Append(value.ParameterName);
          }
          else if (wasInsert)
          {
              //
              // NOTE: This was part of an INSERT statement and we know the table
              //       has an integer primary key.  This should not fail unless
              //       something (e.g. a trigger) causes the last_insert_rowid()
              //       function to return an incorrect result.
              //
              commandText.AppendLine("last_insert_rowid()");
          }
          else /* NOT-REACHED? */
          {
              //
              // NOTE: We cannot simply use the "rowid" at this point because:
              //
              //       1. The last_insert_rowid() function is only valid after
              //          an INSERT and this was an UPDATE.
              //
              throw new NotSupportedException(String.Format(
                  "Missing value for INSERT key member '{0}' in table '{1}'.",
                   (primaryKeyMember != null) ? primaryKeyMember.Name : "<unknown>",
                   table.Name));
          }
      }
      else if (DoAllKeyMembersHaveValues(translator, keyMembers, out missingKeyMember))
      {
          foreach (EdmMember keyMember in keyMembers)
          {
              commandText.Append(" AND ");
              commandText.Append(GenerateMemberTSql(keyMember));
              commandText.Append(" = ");

              // Retrieve member value SQL. the translator remembers member values
              // as it constructs the DML statement (which precedes the "returning"
              // SQL).
              DbParameter value;

              if (translator.MemberValues.TryGetValue(keyMember, out value))
              {
                  //
                  // NOTE: Use the primary key value that was specified as part the
                  //       associated INSERT/UPDATE statement.  This also applies
                  //       to composite primary keys.
                  //
                  commandText.Append(value.ParameterName);
              }
              else /* NOT-REACHED? */
              {
                  //
                  // NOTE: We cannot simply use the "rowid" at this point because:
                  //
                  //       1. This associated INSERT/UPDATE statement appeared to
                  //          have all the key members availab;e however, there
                  //          appears to be an inconsistency.  This is an internal
                  //          error and should be thrown.
                  //
                  throw new NotSupportedException(String.Format(
                      "Missing value for {0} key member '{1}' in table '{2}' " +
                      "(internal).", wasInsert ? "INSERT" : "UPDATE",
                      (keyMember != null) ? keyMember.Name : "<unknown>",
                      table.Name));
              }
          }
      }
      else if (wasInsert) /* NOT-REACHED? */
      {
          //
          // NOTE: This was part of an INSERT statement; try using the "rowid"
          //       column to fetch the most recently inserted row.  This may
          //       still fail if the table is a WITHOUT ROWID table -OR-
          //       something (e.g. a trigger) causes the last_insert_rowid()
          //       function to return an incorrect result.
          //
          commandText.Append(" AND ");
          commandText.Append(SqlGenerator.QuoteIdentifier("rowid"));
          commandText.Append(" = ");
          commandText.AppendLine("last_insert_rowid()");
      }
      else /* NOT-REACHED? */
      {
          //
          // NOTE: We cannot simply use the "rowid" at this point because:
          //
          //       1. The last_insert_rowid() function is only valid after
          //          an INSERT and this was an UPDATE.
          //
          throw new NotSupportedException(String.Format(
              "Missing value for UPDATE key member '{0}' in table '{1}'.",
               (missingKeyMember != null) ? missingKeyMember.Name : "<unknown>",
               table.Name));
      }
      commandText.AppendLine(";");
    }
        public static Expression GetEnumeratorExpression(
            DbExpression predicate,
            DbModificationCommandTree commandTree,
            DbContainer container,
            out ITable table)
        {
            TransformVisitor visitor = new TransformVisitor(container.TypeConverter);
            visitor.TableProvider = container;

            // Get the source expression
            ConstantExpression source =
                visitor.Visit(commandTree.Target.Expression) as ConstantExpression;

            // This should be a constant expression
            if (source == null)
            {
                throw new InvalidOperationException();
            }

            table = source.Value as ITable;

            // Get the the type of the elements of the table
            Type elementType = TypeHelper.GetElementType(source.Type);

            // Create context
            ParameterExpression context = Expression.Parameter(elementType, "context");
            using (visitor.CreateVariable(context, commandTree.Target.VariableName))
            {
                // Create the predicate expression
                LambdaExpression predicateExpression =
                    Expression.Lambda(
                        visitor.Visit(predicate),
                        context);

                // Create Where expression
                LinqMethodExpressionBuilder queryMethodBuilder =
                    new LinqMethodExpressionBuilder();

                return queryMethodBuilder.Where(source, predicateExpression);
            }
        }