CAML Query checking for NULL Parameters - sharepoint-2010

I've poured through various articles but haven't found an answer to my exact scenario. I've a SharePoint 2010 list with some Query Parameters for filter purposes. My CAML Query works well for filtering except in one circumstance, I'd like a General Display All criteria in my query for when the listview is first hit (i.e. my client will actively be able to see/page/sort the data without first having to search the list).
If I was just filtering the list fields I'd be set, but since I'm referencing Query Parameters in my CAML I'm receiving SOAP errors in SharePoint Designer.
The SQL equivalent would be: Where (#Parameter1 is null and #Parameter2 is null and #Parameter3 is null...)
I've tried this structure:
<Or Group="true">
<And>
<And>
<IsNull>
<FieldRef Name ="Title"/>
<Value Type="Text">{RollNum}</Value>
</IsNull>
<Gt>
<FieldRef Name="ID"/>
<Value Type="Counter">
<IfEqual>
<Expr1><![CDATA[{Param1}]]></Expr1>
<Expr2/>
<Then>0</Then>
<Else>2147483647</Else>
</IfEqual>
</Value>
</Gt>
</And>
<IsNull>
<FieldRef Name ="RefNumber"/>
<Value Type="Text">{RefNum}</Value>
</IsNull>
</And>
</Or>...the rest of the query, which works fine.
I have a feeling my structure is incorrect.
Thanks in advance,
Brian H.

You can use this syntax to determine if a field is null:
<Where><IsNull><FieldRef Name='YourFieldName' /></IsNull></Where>
You have an extra Value element within IsNull that you should remove.

I decided to use an HTML Form Web Part to achieve my goal (instead of a content editor). The HTML form web part keeps all filter values entered into any boxes, and can be wired up to filter my list using parameters and a custom caml query.

Related

FetchXML next page results

I want to populate a grid with data from Dynamics CRM. I use fetchXML, to get for each page 10 records. I want to get to the next page, to retrieve the next 10 records. But this isn't happening, I'm using XRMToolbox to simulate the fetch query but it returns me the same results, regardless of the page attribute value.
The fetchXML query is:
<fetch version="1.0" output-format="xml-platform" mapping="logical" count="10" page="1" aggregate="true" distinct="false" >
<entity name="webpage" >
<attribute name="url" groupby="true" alias="url" />
<attribute name="webpageid" aggregate="count" alias="top" />
<order descending="true" alias="top" />
</entity>
</fetch>
If I change the page attribute value, say to 10 the response won't be different.
Can anyone help me with this?
UPDATE
After many tests with XRMToolbox I've come to conclusion that this query won't listen, whatever page I provide to it. This is because of the aggregate attribute. If I remove it and of course remove the count aggregate, then changing the page attribute will actually fetch for me the next page results.
So in summary page attribute doesn't like the aggregate attribute. Maybe this can work with paging cookies, but I haven't tested it yet, I will test it and update this post.
To implement paging you need to use not only page number/records per page attributes but paging cookie as well. This msdn article provides all code you need to implement paging.

Quickest method for matching nested XML data against database table structure

I have an application which creates datarequests which can be quite complex. These need to be stored in the database as tables. An outline of a datarequest (as XML) would be...
<datarequest>
<datatask view="vw_ContractData" db="reporting" index="1">
<datefilter modifier="w0">
<filter index="1" datatype="d" column="Contract Date" param1="2009-10-19 12:00:00" param2="2012-09-27 12:00:00" daterange="" operation="Between" />
</datefilter>
<filters>
<alternation index="1">
<filter index="1" datatype="t" column="Department" param1="Stock" param2="" operation="Equals" />
</alternation>
<alternation index="2">
<filter index="1" datatype="t" column="Department" param1="HR" param2="" operation="Equals" />
</alternation>
</filters>
<series column="Turnaround" aggregate="avg" split="0" splitfield="" index="1">
<filters />
</series>
<series column="Requested 3" aggregate="avg" split="0" splitfield="" index="2">
<filters>
<alternation index="1">
<filter index="1" datatype="t" column="Worker" param1="Malcom" param2="" operation="Equals" />
</alternation>
</filters>
</series>
<series column="Requested 2" aggregate="avg" split="0" splitfield="" index="3">
<filters />
</series>
<series column="Reqested" aggregate="avg" split="0" splitfield="" index="4">
<filters />
</series>
</datatask>
</datarequest>
This encodes a datarequest comprising a daterange, main filters, series and series filters. Basically any element which has the index attribute can occur multiple times within its parent element - the exception to this being the filter within datefilter.
But the structure of this is kind of academic, the problem is more fundamental:
When a request comes through, XML like this is sent to SQLServer as a parameter to a stored proc. This XML is shredded into a de-normalised table and then written iteratively to normalised tables such as tblDataRequest (DataRequestID PK), tblDataTask, tblFilter, tblSeries. This is fine.
The problem occurs when I want to match a given XML defintion with one already held in the DB. I currently do this by...
Shredding the XML into a de-normalised table
Using a CTE to pull all the existing data in the database into that same de-normalised form
Matching using a huge WHERE condition (34 lines long)
..This will return me any DataRequestID which exactly matches the XML given. I fear that this method will end up being painfully slow - partly because I don't believe the CTE will do any clever filtering, it will pull all the data every single time before applying the huge WHERE.
I have thought there must be better solutions to this eg
When storing a datarequest, also store a hash of the datarequest somehow and simply match on that. In the case of collision, use the current method. I wanted however to do this using set-logic. And also, I'm concerned about irrelevant small differences in the XML changing the hash - spurious spaces etc.
Somehow perform the matching iteratively from the bottom up. Eg produce a list of filters which match on the lowest level. Use this as part of an IN to match Series. Use this as part of an IN to match DataTasks etc etc. The trouble is, I start to black-out when I think about this for too long.
Basically - Has anyone ever encountered this kind of problem before (they must have). And what would be the recommended route for tackling it? example (pseudo)code would be great :)
To get rid of the possibility of minor variances, I'd run the request through an XML transform (XSLT).
Alternatively, since you've already got the code to parse this out into a denormalized staging table that's fine too. I would then simply using FOR XML to create a new XML doc.
Your goal here is to create a standardized XML document that respects ordering where appropriate and removes inconsistencies where it is not.
Once that is done, store this in a new table. Now you can run a direct comparison of the "standardized" request XML against existing data.
To do the actual comparison, you can use a hash, store the XML as a string and do a direct string comparison, or do a full XML comparison like this: http://beyondrelational.com/modules/2/blogs/28/posts/10317/xquery-lab-36-writing-a-tsql-function-to-compare-two-xml-values-part-2.aspx
My preference, as long as the XML is never over 8000bytes, would be to create a unique string (either VARCHAR(8000) or NVARCHAR(4000) if you have special character support) and create a unique index on the column.

SP 2010 Query CAML - How to sort by multivalue colum lookup field?

I'm trying to sort a list where a column is based on multiple value on a lookup field with the following statement:
<OrderBy>
<FieldRef Name='LookupFieldName' Ascending='TRUE' LookupValue='TRUE' />
</OrderBy>
If I uncheck "Allow multiple values" from column settings it works fine, but not with multiple values enabled.
Have you some suggestions?
Why SP can't sort on concatenation of ID#Value (eg. 1#Value1;2#Value2) ?
Thanks
You should be able to treat the addtional columns as any other column. In this example, Attorney1_x003a_EmpID is one of the multiple values:
<Query>
<OrderBy>
<FieldRef Name="Attorney1" Ascending="False" />
<FieldRef Name="Attorney1_x003a_EmpID" Ascending="False" />
</OrderBy>
</Query>

Sharepoint 2010 Client Object Model - Large Library - Find item without iteration

I have a large document library (at the moment ~6000 documents) and I need to find a document based on a custom field value (custom column on the library).
Is there a way of getting this document back without iterating through all 6000 documents?
I understand that an iteration must occur at some point, but I would prefer it to happen on the SharePoint server side, rather than transfer them all to the client side then cherry pick the document.
Thanks
You can query Sharepoint. You issue a CAML query which is executed on the server and brings back only items that match the criteria that you specified. You specify the name of the custom column to search on and you specify the value to find. For efficiency , you can ask only for a few fields back (document url for example). So, you do not need to iterate over documents in the list to find the item.
You can find some discussion here:
http://msdn.microsoft.com/en-us/library/ee956524.aspx and you can also find examples how to do it from javascript or silvelight.
Example CAML:
CamlQuery camlQuery = new CamlQuery();
camlQuery.ViewXml =
#"<View>
<Query>
<Where>
<Eq>
<FieldRef Name='FileLeafRef'/>
<Value Type='Text'>Test.docx</Value>
</Eq>
</Where>
<RowLimit>1</RowLimit>
</Query>
</View>";

How can I make a view(SPView) with data will be filtered by filter condition form url parameter?

Example, I have some groups and some items belong to these group. Now, I want to list items of arbitrary group by url like http://sp2010/Lists/items.aspx?groupid=1.
I maked a SPView like
SPView view = SPList.DefaultView;
view.Query = "<Where>
<Eq>
<FieldRef Name=\"Group\" LookupId=\"TRUE\">
<Value Type=\"Lookup\"><GetVar Name=\"GroupId\"></Value>
</Eq>
</Where>";
view.Update();
It work on sharepoint 2007, but unfortunately it don't work on sharepoint 2010.
Try FilterField and FilterValue:
http://sp2010/Lists/MyList/AllItems.aspx?FilterField1=group&FilterValue1=Group%20Name
Note that the value of FilterField is the internal name of the field, not the display name.