OData - converting parameter entity set to LINQ - linq

I have an OData URI that works as I want, passing a value for a parameter called gridsize and retrieving the data from Results. This is the URI and it works fine:
http://<webservice>/MULTI_POINT_PARAMParameters(gridsize=0.1m)/Results
I am trying to get the above URI to work using LINQ. I am using an MVC service reference to generate the proxy class. So I tried this LINQ:
var query = (from x in context.MULTI_POINT_PARAMParameters
where
x.gridsize == 0.1M
select x);
However the above LINQ generates this URI, which fails saying "segement not found":
http://<webservice>/MULTI_POINT_PARAMParameters()?$filter=gridsize eq 0.1M}
What I really want LINQ to generate is this, which I know works:
http://<webservice>/MULTI_POINT_PARAMParameters(gridsize=0.1m)/Results
How can I get LINQ to generate the URI I want? I've looked at Linq2rest but could not see how it can help me if I want to explicitly code the LINQ terms myself, rather than have Linq2rest generate "hidden" terms I cannot see.

As far as my knowledge if you want to add filter in OData you have to use "$filter".
if you want to use "MULTI_POINT_PARAMParameters(gridsize=0.1m)" then you might have to use dynamic generation of LINQ.
After dynamic generation your query might look something like this
var query = (from x in context.MULTI_POINT_PARAMParameters(gridsize=0.1m)
select x);
I am just trying to give you a direction to think.Lets see what others have opinion on your question.

Related

Calling the right URI with ODATA using ODataClient with Expand

I have two tables which are related to each other and I would like to perform some querying with filters on both tables (one for each)
I am using a controller in c# that looks like this :
var list =
await client.For("T_Project")
.Filter("IsQuote eq false")
.Expand("T_Ref_StatusProject")
.Filter("Final eq false")
.FindEntriesAsync();
Here is the URI that I get with this code :
http://localhost:12494/gp/T_Project?$filter=(IsQuote eq false) and (Final eq false)&$expand=T_Ref_StatusProject
However, I get an error saying bad request. I figure the one I want would look something like
http://localhost:12494/gp/T_Project?$filter=(IsQuote%20eq%20false)&$expand=T_Ref_StatusProject($filter=Final%20eq%20true)
The result is, however, exactly the same as if I didn't put any filter for the expand table.
So I have actually two question. How can I make it work in my c# code and what is the right URL syntax for it. I figure answering the first one will answer the second one.
My UI project (the one with the sample code) have Simple.OData.Client(5.0.0 alpha2) installed (which include Microsoft.Odata.Code (6.15.0)
My API have Microsoft.ASPNet.Odata V5.9.1 installed
Thanks
According to the ODATA documentation filtering on nested properties would look like this:
http://localhost:12494/gp/T_Project?$filter=(IsQuote eq false) and (T_Ref_StatusProject/any(d:d/Final eq false))
See QueryOptions 5.1.1.10.1 any, http://docs.oasis-open.org/odata/odata/v4.0/errata03/os/complete/part2-url-conventions/odata-v4.0-errata03-os-part2-url-conventions-complete.html, see also "Addressing Derived Types" in the document which describes the concept in general.
I cannot help you on the first part of your question, as I am not using the C# client. But maybe you can check if the Filter() method accepts a lambda expression, where you can specify an expression that directly corresponds to the expanded entity.

MSCRM 2011 EntitCollection and LINQ empty resultset

I have an EntityCollection ec in C# which has been populated with all Accounts.
Now I want another List or EntityCollection from ec which has all the accounts with status active.
I am using Linq for the same.
But both form of LINQ returns a an empty result while ec has 354 number of records
var activeCRMEC = (from cl in ec.Entities
where cl.Attributes["statecode"].ToString()=="0"
select cl);
OR
var activeCRMEC = ec.Entities.Where(x => x.Attributes["statecode"].ToString() == "0");
Each time the resultset is empty and I am unable to iterate over it. And 300 or so accounts are active, I have checked.
Same thing happens when I use some other attribute such as name etc.
Please be kind enough to point out my mistake.
You can Generate Early Bound Classes to write Linq Queries.
or Else
You can Write Linq Queries Using Late Bound Using OrganizationServiceContext Class.
For Your Reference:
OrganizationServiceContext OrgServiceCOntext = new OrganizationServiceContext(service);
var RetrieveAll = OrgServiceCOntext.CreateQuery("account").
ToList().Where(w => (w.GetAttributeValue<OptionSetValue>("statecode").Value ==0)).Select(s=>s);
I'll give you a few hints, and then tell you what I'm guessing your issue is.
First, use early bound entities. If you've never generated them before, use the earlybound generator, you'll save yourself a lot headaches.
Second, if you can't use early bound entities, use the GetAttribute() method on the Entity class. It'll convert types for you, and handle null reference issues.
Your LINQ expressions look to be correct, so either the ec.Entities doesn't have any entities in it that match the criteria of "statecode" equaling 0, or you possibly have some differed execution occurring on your IEnumerables. Try calling ToList() on the activeCRMEC immediately after the LINQ statement to ensure that is not your issue.
The statecode is an OptionSetValue, you should cast it in this way
((OptionSetValue)cl.Attributes["statecode"]).Value == 0
or
cl.GetAttributeValue<OptionSetValue>("statecode").Value == 0
Both ways are valid and you should ask for the Value that it is an int.
Hope this can help you.

LINQ - to XML Schema - import of multiple XSD files (.NET)

My Goal:
I would like to search for elements in large XML Schema spec. compound from multiple XSD files (with use of import).
Is is possible to use the LINQ? How can I store whole SOM (schema object model) into memory and then ask?
I tried:
Dim reader As XmlTextReader = New XmlTextReader(path)
Dim myschema As XmlSchema = XmlSchema.Read(reader, AddressOf ValidationCallback)
But I have no idea how to use the LINQ here.
The best way to manage multiple schemas is to use an XmlSchemaSet; add your schema(s) to an XmlSchemaSet and then compile it. This should answer your "SOM into memory".
For how to use LINQ against a compiled XmlSchemaSet, it very much depends on the type of problem you're trying to solve. For example, let's say you're trying to get all the elements in an XML namespace. You might write something like this (I realize I've phrased it in C#, I hope you're ok with it).
XmlSchemaSet xset = new XmlSchemaSet();
xset.Add(XmlSchema.Read(...);
xset.Compile();
var query = from XmlSchemaElement element in xset.GlobalElements.Values where element.QualifiedName.Namespace == "urn:tempuri-org:mine" select element;
foreach(XmlSchemaElement element in query) DoSomething();
Another example might be use the Distinct clause to collect the set of XML namespaces that make up your set.
List<string> query1 = (from XmlSchema schema in xset.Schemas() select schema.TargetNamespace).ToList();
IEnumerable<string> xmlns = query1.Distinct();
I hope these give you an idea...

OrderBy("it." + sort) -- Hard coding in LINQ to Entity framework?

I have been trying to use dynamic LINQ to Entity in my application for specifying the OrderBy attribute at runtime. However when using the code as described in the majority of documentation:
var query = context.Customer.OrderBy("Name");
I received the following exception:
System.Data.EntitySqlException: 'Name' could not be resolved in the current scope or context. Make sure that all referenced variables are in scope, that required schemas are loaded, and that namespaces are referenced correctly.
After much searching I found this MSDN page:
http://msdn.microsoft.com/en-us/library/bb358828.aspx
Which included the following code example:
ObjectQuery<Product> productQuery2 = productQuery1.OrderBy("it.ProductID");
This prompted me to change my code to the following:
var query = context.Customer.OrderBy("it.Name");
After this the code works perfectly. Would anyone be able to confirm that this is indeed the correct way to get OrderBy working with LINQ to Entity? I can’t believe that the framework would have been implemented in this way, perhaps I have overlooked something?
Thanks, Matt
The it.Name syntax is ESQL and is indeed specific to the EF. There are good reasons to use this sometimes (e.g., collation specifiers), but it's not what I normally do.
Usually I use standard LINQ expressions:
var query = context.Customer.OrderBy(p => p.Name);
You can also use System.Linq.Dynamic, if you download it from Code Gallery, and then your original query:
var query = context.Customer.OrderBy("Name");
...will work.
No nice way, so far
My answer to this question was to create a stored procedure which has parameter to control sorting.

LINQ multiple where clause

I have a course table which I need to search based on keywords typed in the search box.
Here is a sample query:
SELECT * FROM Courses WHERE
Title LIKE '%word%' OR Title LIKE '%excel%' OR
Contents LIKE '%word%' OR Contents LIKE '%excel%'
How can I convert this in LINQ where LINQ would dynamically generate WHERE statements based on each keywords.
I tried to user PredicateBuilder it works fine as long as the field is VARCHAR. For the "TEXT" fields the quotes are not generated thus causing compiler to give an error message. Here is the SQL generated by PredicateBuilder
SELECT [t0].[CoursesID], [t0].[Title], [t0].[Contents], [t0].[Active],
FROM [dbo].[Courses] AS [t0]
WHERE ([t0].[Title] LIKE '%word%') OR ([t0].[Contents] LIKE %word%) OR
([t0].Title] LIKE '%excel%') OR ([t0].[Contents] LIKE %excel%)
Notice there is no single Quote for the "Contents" field which is a Text field in the database.
Is there any easy way to build WHERE statement and attach it with query? Does anyone know how I can do this without PredicateBuilder?
Thanks in advance.
Since you are working w/ LINQ I suppose you are working against a LINQ-to-SQL data context right? I don't have a spare DataContext lying around to test this, but this should give you some ideas.
I don't know if it will work against data context though, but most of these are pretty basic stuff (chaining OR operator and Contains method call) so it shouldn't cause problem when the query translates to SQL.
First I create a custom function that would build my predicate:
Func<string, Func<DataItem, bool>> buildKeywordPredicate =
keyword =>
x => x.Title.Contains(keyword)
|| x.Contents.Contains(keyword);
This is a function which takes a single string keyword and then return another function which takes a DataItem and checks it against the keyword.
Basically, if you pass in "Stack", you'll get a predicate: x => x.Title.Contains("Stack") || x.Contents.Contains("Stack").
Next, since there are many possible keywords and you need to chain it with an OR operation, I create another helper function to chain 2 predicates together with an OR
Func<Func<DataItem,bool>, Func<DataItem, bool>, Func<DataItem, bool>> buildOrPredicate =
(pred1, pred2) =>
x => pred1(x) || pred2(x);
This function takes 2 predicates and then join them up with an OR operation.
Having those 2 functions, I can then build my where predicate like this:
foreach (var word in keywords) {
filter = filter == null
? buildKeywordPredicate(word)
: buildOrPredicate(filter, buildKeywordPredicate(word));
}
The first line inside the loop basically checks if the filter is null. If it is, then we want a simple keyword filter built for us.
Else if the filter is not null, we need to chain existing filters with an OR operation, so we pass the existing filter and a new keyword filter to buildOrPredicate to do just that.
And then we can now create the WHERE part of the query:
var result = data.Where(filter);
Passing in the complicated predicate we've just built.
I don't know if this will different from using PredicateBuilder but since we are deferring query translation to the LINQ-to-SQL engine, there should not be any problems.
But as I said, I havn't tested it against a real data context, so if there's any problems you can write in the comments.
Here's the console app that I built to test: http://pastebin.com/feb8cc1e
Hope this helps!
EDIT: For a more generic and reusable version which involves properly utilizing the Expression Trees in LINQ, check out Thomas Petricek's blog post: http://tomasp.net/articles/dynamic-linq-queries.aspx
As predicate builder doesn't know the DB type of the property the Contains method is called on, I guess this might be a problem inside linq to sql. Have you tried with a normal query (not with predicate builder) and a TEXT column with Contains?

Resources