예제 #1
0
        private void AddRecordUpdateToBatch(EntityRecord rec)
        {
            CheckCurrentCommand();
            var dbCmd     = _currentCommand.DbCommand;
            var argValues = new List <string>();
            var cmdInfo   = _db.GetDbCommandForSave(rec);

            foreach (var prmInfo in cmdInfo.Parameters)
            {
                var col = prmInfo.SourceColumn;
                //Check if we need to use already defined parameter;
                // this happens when we insert parent and child records with parent having identity primary key column
                if (_updateSet.UsesOutParams && col != null && col.Flags.IsSet(DbColumnFlags.IdentityForeignKey))
                {
                    //Find out parameter that returns the identity of the parent record
                    var parentRec = rec.GetValueDirect(col.Member.ForeignKeyOwner) as EntityRecord;
                    if (parentRec != null && parentRec.CustomTag != null) //it must have customTag already - after recs sorting parent should come first, so it must have idSource already in customTag
                    //parentRec has identity PK
                    {
                        var idSource = (IdentitySource)parentRec.CustomTag;
                        if (idSource.BatchCommand == _currentCommand)
                        {
                            argValues.Add(idSource.Parameter.ParameterName); //if it is the same command, just add ref to parameter
                        }
                        else
                        {
                            //different command - create new parameter, and add action to copy param value from source
                            //NOte - reusing param not allowed, so ' dbCmd.Parameters.Add(idSource.Parameter); '  -this does not work - parameters cannot be shared between commands
                            var dbParam = _driver.AddParameter(dbCmd, prmInfo);
                            //override parameter name
                            dbParam.ParameterName = _driver.DynamicSqlParameterPrefix + "P" + (dbCmd.Parameters.Count - 1);
                            argValues.Add(dbParam.ParameterName);
                            idSource.BatchCommand.AddPostAction(() => dbParam.Value = idSource.Parameter.Value);
                        }
                        // Set value of foreign key
                        idSource.BatchCommand.AddPostAction(() => rec.SetValueDirect(col.Member, idSource.Parameter.Value));
                        continue; //next param
                    } //if parentRec!=null
                }//if

                //Get the value, analyze it, see if it is ok to use literal or it's better to put the value into parameter
                var value = rec.GetValueDirect(col.Member);
                if (value == null)
                {
                    value = DBNull.Value;
                }
                var conv = prmInfo.TypeInfo.PropertyToColumnConverter;
                if (value != DBNull.Value && conv != null)
                {
                    value = conv(value);
                }
                if (BatchShouldUseParameterFor(prmInfo, value))
                {
                    //create parameter
                    var dbParam = _driver.AddParameter(dbCmd, prmInfo);
                    //override parameter name
                    dbParam.ParameterName = _driver.DynamicSqlParameterPrefix + "P" + (dbCmd.Parameters.Count - 1);
                    dbParam.Value         = value;
                    //If it is parameter holding identity returned from stored proc, then save its info in the rec.CustomTag
                    bool isIdentityOut = rec.Status == EntityStatus.New && col.Flags.IsSet(DbColumnFlags.Identity) &&
                                         dbParam.Direction == ParameterDirection.Output;
                    if (isIdentityOut)
                    {
                        rec.CustomTag = new IdentitySource()
                        {
                            BatchCommand = _currentCommand, Parameter = dbParam
                        }
                    }
                    ;

                    //add reference to parameter in arg list
                    var strArg = dbParam.ParameterName;
                    if (dbParam.Direction != ParameterDirection.Input)
                    {
                        strArg = string.Format(_driver.CommandCallOutParamFormat, strArg);
                        //copy value returned from sp into entity property
                        _currentCommand.AddPostAction(() =>
                                                      rec.SetValueDirect(col.Member, dbParam.Value)
                                                      );
                    }
                    argValues.Add(strArg);
                }
                else
                {
                    string argValue;
                    if (value == DBNull.Value)
                    {
                        argValue = "NULL";
                    }
                    else
                    {
                        argValue = prmInfo.TypeInfo.ToLiteral(value);
                    }
                    argValues.Add(argValue);
                } // if BatchShouldUseParameterFor
            }     //foreach prm
            //format method call
            var strArgs = string.Join(", ", argValues);
            var strCall = string.Format(_driver.CommandCallFormat, cmdInfo.FullCommandName, strArgs);

            //append it to sql
            _sqlBuilder.AppendLine(strCall);
        }