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); }