How do I view the SQL that is generated by nHibernate? version 1.2
You can put something like this in your app.config/web.config file :
in the configSections node :
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net"/>
in the configuration node :
<log4net>
<appender name="NHibernateFileLog" type="log4net.Appender.FileAppender">
<file value="logs/nhibernate.txt" />
<appendToFile value="false" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%d{HH:mm:ss.fff} [%t] %-5p %c - %m%n" />
</layout>
</appender>
<logger name="NHibernate.SQL" additivity="false">
<level value="DEBUG"/>
<appender-ref ref="NHibernateFileLog"/>
</logger>
</log4net>
And don't forget to call
log4net.Config.XmlConfigurator.Configure();
at the startup of your application, or to put
[assembly: log4net.Config.XmlConfigurator(Watch=true)]
in the assemblyinfo.cs
In the configuration settings, set the "show_sql" property to true.
I am a bit late I know, but this does the trick and it is tool/db/framework independent.
Instead of those valid options, I use NH Interceptors.
At first, implement a class which extends NHibernate.EmptyInterceptor and implements NHibernate.IInterceptor:
using NHibernate;
namespace WebApplication2.Infrastructure
{
public class SQLDebugOutput : EmptyInterceptor, IInterceptor
{
public override NHibernate.SqlCommand.SqlString
OnPrepareStatement(NHibernate.SqlCommand.SqlString sql)
{
System.Diagnostics.Debug.WriteLine("NH: " + sql);
return base.OnPrepareStatement(sql);
}
}
}
Then, just pass an instance when you open your session. Be sure to do it only when in DEBUG:
public static void OpenSession() {
#if DEBUG
HttpContext.Current.Items[SessionKey] = _sessionFactory.OpenSession(new SQLDebugOutput());
#else
HttpContext.Current.Items[SessionKey] = _sessionFactory.OpenSession();
#endif
}
And that's it.
From now on, your sql commands like these...
var totalPostsCount = Database.Session.Query<Post>().Count();
var currentPostPage = Database.Session.Query<Post>()
.OrderByDescending(c => c.CreatedAt)
.Skip((page - 1) * PostsPerPage)
.Take(PostsPerPage)
.ToList();
.. are shown straight in your Output window:
NH: select cast(count(*) as INT) as col_0_0_ from posts post0_
NH:select post0_.Id as Id3_, post0_.user_id as user2_3_, post0_.Title as
Title3_, post0_.Slug as Slug3_, post0_.Content as Content3_,
post0_.created_at as created6_3_, post0_.updated_at as updated7_3_,
post0_.deleted_at as deleted8_3_ from posts post0_ order by
post0_.created_at desc limit ? offset ?
In the configuration settings, set the "show_sql" property to true.
This will cause the SQL to be output in NHibernate's logfiles courtesy of log4net.
Use sql server profiler.
EDIT (1 year later): As #Toran Billups states below, the NHibernate profiler Ayende wrote is very very cool.
You can also try NHibernate Profiler (30 day trial if nothing else). This tool is the best around IMHO.
This will not only show the SQL generated but also warnings/suggestions/etc
There is a good reference for NHibernate logging at: How to configure Log4Net for use with NHibernate. It includes info on logging all NHibernate-generated SQL statements.
Nhibernate Profiler is an option, if you have to do anything serious.
If you're using SQL Server (not Express), you can try SQL Server Profiler.
Or, if you want to show the SQL of a specific query, use the following method (slightly altered version of what suggested here by Ricardo Peres) :
private String NHibernateSql(IQueryable queryable)
{
var prov = queryable.Provider as DefaultQueryProvider;
var session = prov.Session as ISession;
var sessionImpl = session.GetSessionImplementation();
var factory = sessionImpl.Factory;
var nhLinqExpression = new NhLinqExpression(queryable.Expression, factory);
var translatorFactory = new NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory();
var translator = translatorFactory.CreateQueryTranslators(nhLinqExpression, null, false, sessionImpl.EnabledFilters, factory).First();
var sql = translator.SQLString;
var parameters = nhLinqExpression.ParameterValuesByName;
if ( (parameters?.Count ?? 0) > 0)
{
sql += "\r\n\r\n-- Parameters:\r\n";
foreach (var par in parameters)
{
sql += "-- " + par.Key.ToString() + " - " + par.Value.ToString() + "\r\n";
}
}
return sql;
}
and pass to it a NHibernate query, i.e.
var query = from a in session.Query<MyRecord>()
where a.Id == "123456"
orderby a.Name
select a;
var sql = NHibernateSql(query);
You are asking only for viewing; but this answer explains how to log it to file. Once logged, you can view it in any text editor.
Latest versions of NHibernate support enabling logging through code. Following is the sample code that demonstrates this. Please read the comments for better understanding.
Configuration configuration = new Configuration();
configuration.SetProperty(NHibernate.Cfg.Environment.Dialect, ......);
//Set other configuration.SetProperty as per need
configuration.SetProperty(NHibernate.Cfg.Environment.ShowSql, "true"); //Enable ShowSql
configuration.SetProperty(NHibernate.Cfg.Environment.FormatSql, "true"); //Enable FormatSql to make the log readable; optional.
configuration.AddMapping(......);
configuration.BuildMappings();
ISessionFactory sessionFactory = configuration.BuildSessionFactory();
//ISessionFactory is setup so far. Now, configure logging.
Hierarchy hierarchy = (Hierarchy)LogManager.GetRepository(Assembly.GetEntryAssembly());
hierarchy.Root.RemoveAllAppenders();
FileAppender fileAppender = new FileAppender();
fileAppender.Name = "NHFileAppender";
fileAppender.File = logFilePath;
fileAppender.AppendToFile = true;
fileAppender.LockingModel = new FileAppender.MinimalLock();
fileAppender.Layout = new PatternLayout("%d{yyyy-MM-dd HH:mm:ss}:%m%n%n");
fileAppender.ActivateOptions();
Logger logger = hierarchy.GetLogger("NHibernate.SQL") as Logger;
logger.Additivity = false;
logger.Level = Level.Debug;
logger.AddAppender(fileAppender);
hierarchy.Configured = true;
You can further play with FileAppender and Logger as per your need. Please refer to this answer and this resource for more details. This explains the same with XML configuration; but the same should equally apply to code.
Related
i'm new on Playframework and i need to migrate the CRUD Plugin from Play-1.2.4 to a module on Play-2.5.x. I'm facing some strange problems with the views. For example the form.scala.html component have the following errors :
app\views\tags\crud\form.scala.html:28: not found: type fieldName
app\views\tags\crud\form.scala.html:28: variable fieldsHandler of type Array[String] does not take type parameters.
app\views\tags\crud\form.scala.html:31: not found: value field
Here is a piece of code of the form file :
#(fields: List[String], obj: Object, typ: controllers.CRUD.ObjectType)(body: Html)
#import scala.Predef; var currentObject: Object = null; var currentType: controllers.CRUD.ObjectType = null; var fieldsHandler = new Array[String](10);
#for(fieldName <- fields) {
var am : String = "";
var field = #currentType.getField(fieldName);
#if(field == null){
throw new play.exceptions.TagInternalException("Field not found -> " + #fieldName)
}
#if(field.typ == "text") {
#tags.crud.textField(fieldName, currentObject[fieldName])
}
#if(field.typ == "password") {
#tags.crud.passwordField(fieldName, currentObject[fieldName])
}
#if(field.typ == "binary"){
#tags.crud.fileField(fieldName, currentObject[fieldName], currentObject.id )
}
}
--> 80% of the compile errors are related to variable recognition !
A piece from build.sbt file:
scalaVersion := "2.11.7"
lazy val root = (project in file(".")).enablePlugins(PlayJava, PlayEbean, SbtTwirl)
fork in run := true
Any idea ? Your help will be appreciated. Thanks.
I understood that the principle of the crud plugin is in contradiction with the new logic of compiling scala templates. So I started on a new generic implementation of crud.
Thank you
I am trying to use the TFS API to rollback a changeset.
I tried using all Workspace.Rollback methods but the action does nothing (The GetStatus returned says NoActionNeeded:true).
Has anyone managed to get this to work and can send a working code sample?
From the documentation of the method:
public GetStatus Rollback(
string[] paths,
RecursionType recursion,
VersionSpec itemSpecVersion,
VersionSpec versionFrom,
VersionSpec versionTo,
LockLevel lockLevel,
RollbackOptions options,
string[] itemAttributeFilters
)
I do not understand what the parameter VersionSpec itemSpecVersion means.
It says 'The version spec that identifies the item to which the user is referring.' but then how does it differ from the parameter versionFrom?
What should I pass as the itemAttributeFilters (the last paramter)?
You can rollback changeset programmatically with the following code:
TfsTeamProjectCollection tpc = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("tfsCollectionURL"));
VersionControlServer vcs = (VersionControlServer)tpc.GetService(typeof(VersionControlServer));
string workingDirectory = #"localPath";
string[] workigDnirectoryArr = new string[] { workingDirectory };
Workspace ws = vcs.GetWorkspace("$/serverPath");
int fromCS = 456; //changesetid
int toCS = 495; //changesetid
VersionSpec versionSpecFrom = new ChangesetVersionSpec(fromCS);
VersionSpec versionSpecTo = new ChangesetVersionSpec(toCS);
var status = ws.Rollback(workigDnirectoryArr, RecursionType.None,null, versionSpecFrom, versionSpecTo,LockLevel.None,RollbackOptions.None,null);
Put together a very simple database using Hibernate, but notice that quite often I get the Glassdoor server error telling me "Too Many Connections".
I assume this is because I'm not correctly closing my connections when I update/add/remove database items.
Here's an example of what I do in my updateEntry.jsp-- any blantant issues? If not I can post my removeEntry.jsp and newEntry.jsp:
<%#page import="java.util.Date" %>
<%#page import="org.hibernate.Session" %>
<%#page import="org.hibernate.SessionFactory" %>
<%#page import="org.hibernate.Transaction" %>
<%#page import="org.hibernate.cfg.Configuration" %>
<%#page import="java.util.Date" %>
<%
String nId = request.getParameter("pID");
String naddress = request.getParameter("pAddress");
String nstatus = request.getParameter("pStatus");
String nassigned = request.getParameter("pAssigned");
String nnote = request.getParameter("pNote");
if (!naddress.equals("undefined"))
{
// This step will read hibernate.cfg.xml and prepare hibernate for use
org.hibernate.SessionFactory sessionFactory1 = new org.hibernate.cfg.Configuration().configure().buildSessionFactory();
org.hibernate.Session session1 = sessionFactory1.openSession();
org.hibernate.Query query1 = session1.createQuery("update Leads set Address = :naddr where Id = :nid");
query1.setParameter("nid", nId);
query1.setParameter("naddr", naddress);
query1.executeUpdate();
//out.println("Update successfully with: " + naddress);
// Actual contact insertion will happen at this step
session1.flush();
session1.close();
}
if (!nstatus.equals("undefined"))
{
// This step will read hibernate.cfg.xml and prepare hibernate for use
org.hibernate.SessionFactory sessionFactory2 = new org.hibernate.cfg.Configuration().configure().buildSessionFactory();
org.hibernate.Session session2 = sessionFactory2.openSession();
org.hibernate.Query query2 = session2.createQuery("update Leads set Status = :nstatus where Id = :nid");
query2.setParameter("nid", nId);
query2.setParameter("nstatus", nstatus);
query2.executeUpdate();
//out.println("Update successfully with: " + nstatus);
// Actual contact insertion will happen at this step
session2.flush();
session2.close();
}
if (!nassigned.equals("undefined"))
{
// This step will read hibernate.cfg.xml and prepare hibernate for use
org.hibernate.SessionFactory sessionFactory3 = new org.hibernate.cfg.Configuration().configure().buildSessionFactory();
org.hibernate.Session session3 = sessionFactory3.openSession();
org.hibernate.Query query3 = session3.createQuery("update Leads set Assigned = :nassigned where Id = :nid");
query3.setParameter("nid", nId);
query3.setParameter("nassigned", nassigned);
query3.executeUpdate();
//out.println("Update successfully with: " + nassigned);
// Actual contact insertion will happen at this step
session3.flush();
session3.close();
}
if (!nnote.equals("undefined"))
{
// This step will read hibernate.cfg.xml and prepare hibernate for use
org.hibernate.SessionFactory sessionFactory4 = new org.hibernate.cfg.Configuration().configure().buildSessionFactory();
org.hibernate.Session session4 = sessionFactory4.openSession();
org.hibernate.Query query4 = session4.createQuery("update Leads set Notes = :nnote where Id = :nid");
query4.setParameter("nid", nId);
query4.setParameter("nnote", nnote);
query4.executeUpdate();
//out.println("Update successfully with: " + nnote);
// Actual contact insertion will happen at this step
session4.flush();
session4.close();
}
%>
You should not initialize hibernate within the JSP, you just initialize once when the context start.
Normally you would put the hibernate factory initialization upon context initialization, then you should get the session from the factory once at the start of every request.
#WebListener
public class HibernateListener implements ServletContextListener {
public static final String ENTITY_MANAGER = "entity.manager";
public void contextInitialized(ServletContextEvent evt) {
SessionFactory sessionFactory = new Configuration()
.configure().buildSessionFactory();
evt.getServletContext()
.setAttribute(ENTITY_MANAGER, sessionFactory);
}
public void contextDestroyed(ServletContextEvent evt) {
SessionFactory sessionFactory = (SessionFactory) evt.getServletContext()
.getAttribute(ENTITY_MANAGER);
sessionFactory.close();
}
}
Then you could get the session picking the entityManager from the servletContext.
<% SessionFactory factory =(SessionFactory) session.getServletContext()
.getAttribute(HibernateListener.ENTITY_MANAGER); %>
I think you should carefully read Hibernate Quickstart Guide
Does anyone know if there is a way to deploy a BrowserFormWebPart (custom InfoPath form for a list content type) using standard AllUsersWebPart element and a CDATA section for the properties? So far I have tried without success. Any help is appreciated.
After 2 days of research - Following code works
private void UpdateInfoPathForms(SPSite oSite)
{
UpdateInfoPath(oSite, "Lists/Audit Calendar/Item/newifs.aspx");
UpdateInfoPath(oSite, "Lists/Audit Calendar/Item/displayifs.aspx");
UpdateInfoPath(oSite, "Lists/Audit Calendar/Item/editifs.aspx");
}
private void UpdateInfoPath(SPSite oSite, string formFileLocation)
{
var file = oSite.RootWeb.GetFile(formFileLocation);
using (SPLimitedWebPartManager manager = file.GetLimitedWebPartManager(System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared))
{
try
{
var wp1 = new Microsoft.Office.InfoPath.Server.Controls.WebUI.BrowserFormWebPart();
wp1.SubmitBehavior = Microsoft.Office.InfoPath.Server.Controls.WebUI.SubmitBehavior.FormDefault;
wp1.FormLocation = "~list/Item/template.xsn";
wp1.ContentTypeId = oSite.RootWeb.Lists["Audit Calendar"].ContentTypes["Item"].Id.ToString();
IListWebPart listWebpart = wp1 as IListWebPart;
listWebpart.ListId = oSite.RootWeb.Lists["Audit Calendar"].ID;
if (formFileLocation.Contains("newifs.aspx"))
{
listWebpart.PageType = PAGETYPE.PAGE_NEWFORM;
}
else if (formFileLocation.Contains("displayifs.aspx"))
{
wp1.ListFormMode = Microsoft.Office.InfoPath.Server.Controls.WebUI.ListFormMode.ReadOnly;
listWebpart.PageType = PAGETYPE.PAGE_DISPLAYFORM;
}
else if (formFileLocation.Contains("editifs.aspx"))
{
listWebpart.PageType = PAGETYPE.PAGE_EDITFORM;
}
listWebpart.ViewFlags = SPViewFlags.None;
manager.AddWebPart(wp1, "Main", 0);
manager.SaveChanges(wp1);
}
finally
{
manager.Web.Dispose();
}
}
I have had the same problem. Here is what I tried:
<AllUsersWebPart WebPartZoneID="Main" WebPartOrder="2">
<![CDATA[
<webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<type name="Microsoft.Office.InfoPath.Server.Controls.WebUI.BrowserFormWebPart, Microsoft.Office.InfoPath.Server, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" />
<importErrorMessage>Cannot import this Web Part.</importErrorMessage>
</metaData>
<data>
<properties>
<property name="ChromeType" type="chrometype">None</property>
<property name="HelpMode" type="helpmode">Modeless</property>
<property name="ChromeState" type="chromestate">Normal</property>
</properties>
</data>
</webPart>
</webParts>]]>
</AllUsersWebPart>
I then have a Feature Receiver that configures the web part:
using (SPLimitedWebPartManager manager = file.GetLimitedWebPartManager(PersonalizationScope.Shared))
{
try
{
BrowserFormWebPart webpart = GetWebPart(manager);
webpart.SubmitBehavior = SubmitBehavior.FormDefault;
webpart.FormLocation = "~list/MyList/template.xsn";
webpart.ContentTypeId = "0x01003C8AD6E14DAD5342BBFAA84E63F8022C";
manager.SaveChanges(webpart);
}
finally
{
manager.Web.Dispose();
}
}
The BrowserFormWebPart properties are required for getting the form to display, but for some reason, setting those properties in the AllUsersWebPart section did not work. The form displays and I can fill it out, but the values from the form do not get inserted into the fields of the list item. I added the following section to the Feature Receiver to try to get the form to tie into the fields of the list item:
IListWebPart listWebpart = webpart as IListWebPart;
listWebpart.PageType = PAGETYPE.PAGE_EDITFORM;
listWebpart.ViewFlags = SPViewFlags.None;
Unfortunately, no joy. And that is as far as I got. Hopefully you'll have better luck.
I have created a workflow is SharePoint Designer and associated it with a list. The workflow creates an approval process, so SharePoint creates a task in the Tasks list so that the user can approve or reject.
What I need to do is to approve or reject the task without opening the task in the task list. After some research I figured that I can use SharePoint Web Services. However I feel lost as I don't know which service, e.g. Lists.asmx, and which method, e.g. UpdateListItems, to call.
Can someone guide me through the following:
1- Is it feasible to approve a workflow task SharePoint Web Services?
2- Can you show me an example of how to approve a task, e.g. which service and method to call and what should be the parameters?
Update
I have been using the following XML to set the workflow to complete:
batchElement.InnerXml = "<Method ID='1' Cmd='Update'>" // Also used Moderate
+ "<Field Name='ID'>115</Field>"
+ "<Field Name='Status'>Completed</Field>"
+ "<Field Name='FormData'>Completed</Field>" // Also used Approved
+ "<Field Name='WorkflowOutcome'>Approved</Field>"
+ "<Field Name='Completed'>True</Field>"
+ "<Field Name='PercentComplete'>1</Field>"
+ "<Field Name='_ModerationStatus'>0</Field>"
+ "</Method>";
The task list item is updated but the WorkflowOutcome remains empty and the workflow doesn't move to the next step.
What else I am missing?
Update #2
I am suspecting the ExtendedProperties of the task list item. For an item that was completed using the UI, the ExtendedProperties shows ws_TaskStatus='Approved'. However for an item that was approved using the code ws_TaskStatus doesn't exist.
Update #3
From an MSDN post, I was told to use the Workflow.asmx instead of the Lists.asmx.
I have used the following code:
WorkflowService.Workflow listProxy = new WorkflowService.Workflow();
listProxy.Url = "http://<server_name>/_vti_bin/workflow.asmx";
listProxy.UseDefaultCredentials = true;
int todoID = 118;
Guid tasklistID = new Guid("{79ABFDE7-0398-4AD7-918A-0D40204E7726}");
string itemURL = "http://<server_name>/TestLibrary/volshext.log";
XmlDocument taskData = new XmlDocument();
taskData.Load(#"..\..\TaskData.xml");
try
{
XmlNode response = listProxy.AlterToDo(itemURL, todoID, tasklistID, taskData.DocumentElement);
Console.WriteLine(response.InnerText);
}
The XML I am using to approve the task is
<my:myFields xmlns:my="http://schemas.microsoft.com/office/infopath/2003/myXSD" >
<my:TaskStatus>#</my:TaskStatus>
<my:Comments />
<my:DelegateTo />
<my:NewDescription>Please approve Workflow Demo</my:NewDescription>
<my:NewDueDate />
<my:RequestTo />
<my:Decline>0</my:Decline>
<my:dcr>0</my:dcr>
<my:Status>Completed</my:Status>
</my:myFields>
But again the task was updated but the workflow didn't move forward.
Update #4
I have made one last trial with SharePoint server object model however, again, the task is updated but the workflow is not moving forward.
Here is my code:SPSite site = new SPSite("http://sitenamehere/");
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists["Shared Documents"];
//SPListItem item = list.GetItemById(18);
SPListItem item = list.GetItemByUniqueId(new Guid("5300d16e-94f8-4338-8206-4a57ab7c369b"));
SPWorkflow workflow = item.Workflows[0];
SPWorkflowTask task = workflow.Tasks[0];
Hashtable ht = new Hashtable();
ht[SPBuiltInFieldId.Completed] = "TRUE";
ht["Completed"] = "TRUE";
ht[SPBuiltInFieldId.PercentComplete] = 1.0f;
ht["PercentComplete"] = 1.0f;
ht["Status"] = "Completed";
ht[SPBuiltInFieldId.TaskStatus] = SPResource.GetString(new CultureInfo((int)task.Web.Language, false), Strings.WorkflowStatusCompleted, new object[0]);
//ht["TaskStatus"] = "#";
//ht["ows_TaskStatus"] = "Approved";
//ht["FormData"] = SPWorkflowStatus.Completed;
//ht["Outcome"] = "Approved";
//task.ModerationInformation.Status = SPModerationStatusType.Approved;
web.AllowUnsafeUpdates = true;
SPWorkflowTask.AlterTask((task as SPListItem), ht, true);
}
After a lot of trials and investigation I just had the following code working to approve the task
SPSite site = new SPSite("http://servername/");
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists["TestList"];
SPListItem item = list.GetItemById(22);
SPWorkflow workflow = item.Workflows[0];
SPWorkflowTask task = workflow.Tasks[0];
Hashtable ht = new Hashtable();
ht[SPBuiltInFieldId.Completed] = "TRUE";
ht["Completed"] = "TRUE";
ht[SPBuiltInFieldId.PercentComplete] = 1.0f;
ht["PercentComplete"] = 1.0f;
ht["Status"] = "Completed";
ht[SPBuiltInFieldId.TaskStatus] = SPResource.GetString(new CultureInfo((int)task.Web.Language, false), Strings.WorkflowStatusCompleted, new object[0]);
ht[SPBuiltInFieldId.WorkflowOutcome] = "Approved";
ht["TaskStatus"] = "Approved";
ht["FormData"] = SPWorkflowStatus.Completed;
web.AllowUnsafeUpdates = true;
SPWorkflowTask.AlterTask((task as SPListItem), ht, true);
}
I suspect that ht["TaskStatus"] = "Approved"; is that attribute that solved it. Anyway I will try to narrow on the set of properties that need to be changed.
You can use the following code that uses the lists web service and the UpdateListItems method. The key is to use the Cmd='Moderate'
public static XmlNode UpdateListItemApprove()
{
listservice.Lists listProxy = new listservice.Lists();
string xml = "<Batch OnError='Continue'><Method ID='1' Cmd='Moderate'><Field Name='ID'/><Field Name='FileRef'>http://basesmcdev2/sites/tester1/approvals/KL022030.lic</Field><Field Name=\"_ModerationStatus\" >0</Field></Method></Batch>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
XmlNode batchNode = doc.SelectSingleNode("//Batch");
listProxy.Url = "http://basesmcdev2/sites/tester1/_vti_bin/lists.asmx";
listProxy.UseDefaultCredentials = true;
XmlNode resultNode = listProxy.UpdateListItems("approvals", batchNode);
return resultNode;
}
I'm not sure if Madhur's solution works on the associated item or on the task, but to update the task try:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<UpdateListItems
xmlns="http://schemas.microsoft.com/sharepoint/soap/">
<listName>Tasks</listName>
<updates>
<Batch OnError="Continue" ListVersion="1">
<Method ID="1" Cmd="Update">
<Field Name="ID">199</Field>
<Field Name="Outcome">Approved</Field>
<Field Name="Status">Completed</Field>
<Field Name="ows_TaskStatus">Approved</Field>
</Method>
</Batch>
</updates>
</UpdateListItems>
</soap:Body>
</soap:Envelope>
Info on the service:
http://objectmix.com/sharepoint/800144-updatelistitems-web-service-does-not-update-field.html
Info on the approved field:
http://social.msdn.microsoft.com/Forums/en/sharepointworkflow/thread/6712d379-2df6-4223-9a29-b2e60493f1b6
http://social.msdn.microsoft.com/Forums/en/sharepointworkflow/thread/3dc95190-cc61-4067-ac35-2d1a82fad499