Linq IQueryable.Any() Usage - linq

Below is my code . Please review it .
1. bool isUnavailable = db.Deploys.Where(p =>
p.HostEnvironmentId == Guid.Parse(host.ID) &&
p.Status == (int)DeployStatus.Deploying).AsEnumerable().Any();
This one works.
The following statements doesn't work.
2. bool isUnavailable = db.Deploys.Where(p =>
p.HostEnvironmentId == Guid.Parse(host.ID) &&
p.Status == (int)DeployStatus.Deploying).Any();//Error
The Exception is
An exception of type 'System.NotSupportedException' occurred in
Microsoft.Data.Services.Client.DLL but was not handled in user code
Additional information: The method 'Any' is not supported.
3. bool isUnavailable = db.Deploys.Where(p =>
p.HostEnvironmentId.ToString() == host.ID &&
p.Status == (int)DeployStatus.Deploying).AsEnumerable().Any();//Error
The Exception is
An exception of type 'System.NotSupportedException' occurred in
Microsoft.Data.Services.Client.DLL but was not handled in user code
Additional information: The expression (([10007].HostEnvironmentId.ToString() ==
"b7db845b-cec4-49af-8f4b-b419a4e44331") And ([10007].Status == 90)) is not supported.
The Deploys Class is the model which is built in the client proxy class of WCF Data service. I was using "add service reference" to create WCF client proxy class.
But as to the Generic List,
Supposed below code. it will works fine.
4.bool b=servers.Where(d =>
d.status == (int)Enums.ServerStatus.Deploying ||
d.status == int)Enums.ServerStatus.Unavailable).Any();
My question is
Why same way used in different Class got different result .(See the method 2 and method 4).
Why 2 and 3 don't work.
Hope someone can help me . Thanks

LINQ has a concept of 'providers'. When working with LINQ over different data sources, different things need to happen for identical LINQ queries depending on the data source.
For example, when you want to use LINQ to query a database, the LINQ query needs to be converted to an SQL query. When the data source is OData, the query needs to be converted to a URL. There are different providers for each, and each provider supports a different subset of LINQ operators and other language constructs. LINQ-to-SQL, Entity Framework and LINQ-to-NHibernate are three popular LINQ providers for database access.
In your case, you are using WCF Data Services which includes a LINQ provider for OData. Since in OData there is no way to express the .Any() LINQ operator, attempting to use it in a query with that provider throws an exception. By using .AsEnumerable() you're essentially saying to stop using the OData LINQ provider at that point and start using the LINQ-to-Objects provider (which isn't technically a provider, but conceptually you can think of it as one). That means only what comes before .AsEnumerable() will be converted to an OData query, causing to retrieve all the Deploy entities that match the .Where(), and after they have all been transferred to the client, the client will perform the .Any() by checking the number of Deploy entities it has received. This of course is bad if there are many such entities, it will cause unwanted transfer of data over the network when all you wanted is the server side (database probably) to check if there are any. Unfortunately, .Any() is not supported by OData 1.0 (I don't know about OData 2.0).
Also, OData may not support .ToString() either. You may need to compare the Guid structures directly, i.e. create a local variable that contains the GUID value you want to compare:
var g = Guid.Parse("b7db845b-cec4-49af-8f4b-b419a4e44331")`
And then in the query compare the GUIDs like so:
x.HostedEnvironment == g

Related

DocumentDB LINQ query not converting enums correctly

According to this and this, The DocumentDb LINQ provider is supposed to use custom JsonConverters when generating queries that use enums (as far back as version 1.10.0). But we're not seeing that behavior.
My project is referencing Microsoft.Azure.DocumentDb 1.13.1 and we're still seeing a LINQ query that converts an enum to its numeric value. A Where() predicate like this
request => request.Source == sourceId && request.State == state
generates a query like this
{SELECT * FROM root WHERE ((root["Source"] = "5c196602-1a60-406a-81cd-1be5ac23eb18") AND (root["State"] = 0))) }
State is an enum and is correctly serialized/stored in the DB as its string value, per our serializer settings on the docdb client object. This is not a problem with serializing/deserializing the objects to/from documents - that works as expected.
What might we be doing wrong? Is it documented somewhere how to enable/utilize this capability? Do we have to register the JSON converters with the LINQ provider or something?
1.13.1 is a version with query serialisation issues so it is a bug with the SDK.
Those issues where fixed after 1.19.1 as you can see here: https://learn.microsoft.com/en-us/azure/cosmos-db/sql-api-sdk-dotnet#a-name11911191
Fixed a bug in which the custom JsonSerializer settings were not being honored for some queries and stored procedure execution
You will have to upgrade to a post 1.19.1 version of the SDK.

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.

OData - converting parameter entity set to 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.

cannot project entities in Linq 2 NHibernate

I'm working with NHibernate 2 in a .Net project and I'm using the Linq2NHibernate provider.
This simple query
var result = from d in session.Linq<Document>()
where d.CreationYear == 2010
select d.ChildEntity).ToList();
throws an exception telling me that is impossible to cast ChildEntity type do Document type.
Why is that?
I also tried to translate it in query methods, having
session.Linq<Document>()
.where(d=>d.CreationYear == 2010)
.select(d=>d.ChildEntity)
.ToList();
Isn't the select method supposed to project an IQueryble into a IQueryble, beeing TResult!=T ?
Try this:
var result = (from d in session.Linq<Document>()
where d.CreationYear == 2010
select new ChildEntityType
{ /* here just do a simple assignments for all ChildEntityType fields
d.ChildEntity */ } ).ToList();
Yes, this could look quite stupid, but linq2nhibernate sometimes behave very strange, when you try to select just an object.
The old Linq provider is extremely limited and has been unmaintained for several years.
I suggest that you upgrade to the latest stable NHibernate (3.2), which has a much better (and integrated) Linq provider.
can you try this:
session.Linq<Document>()
.Where(d=>d.CreationYear == 2010)
.Select(d=>d.ChildEntity)
.ToList<T>(); //where T is typeof(ChildEntity)

NHibernate.LINQ Supported Operators

I'm trying to evaluate NHibernate.LINQ 1.0 without actually writing any code. Ayende has admitted that this version of LINQ support is subpar compared to EF, but for the life of me I can't seem to find a page that explains what's supported and unsupported in this implementation. For example, can I use Skip & Take? What can I not use?
You can check LINQ for NHibernate examples to see tests done by Ayende himself on what's implemented and what's not for this provider.
Some of those generally supported:
Anonymous type creation. new { Person = x.Name }
First(). query.First()
FirstOrDefault(). query.FirstOrDefault()
Single(). query.Single()
SingleOrDefault(). query.SingleOrDefault()
Aggregate(). query.Aggregate((x1,x2) => x1)
Contains(). query.Where(x => x.Name.Contains("Foo"))
StartsWith().
EndsWith().
Substring(). where db.Methods.Substring(e.FirstName, 1, 2) == "An"
Sub-queries. query.Where(x => x.Company.Id == 4)
Count(). query.Where(x => x.Relatives.Count > 0)
Any(). query.Any()
Take(). query.Take(10)
Skip(). query.Take(10).Skip(4)
OrderBy(). orderby x.Name descending
Replace(). AfterMethod = e.FirstName.Replace("An", "Zan"),
CharIndex(). where db.Methods.CharIndex(e.FirstName, 'A') == 1
IndexOf(). where e.FirstName.IndexOf("An") == 1
Problematic:
Group by
Joins
One of my own examples:
query = NSession.Session.Linq<Catalog>()
.Where(acc => acc.Company.Status == "A")
.Where(acc => acc.Id.StartsWith("12-536"))
.Where(acc => acc.Id.EndsWith("92") || acc.Id.EndsWith("67"))
.Take(10).OrderBy(acc => acc.Title);
If you're production application is using the latest stable build 2.1.2.4 like I am, you're stuck with what the NHibernate.Linq provider gives us until NHibernate 3.0 (trunk) gets a stable release and we feel safe enough to use it on major applications. Until then, I'm more than happy with a mixture of NHibernate.Linq and HQL.
The basic test of whether NHibernate can work with a Linq statement is whether you can serialize that statement's expression tree, then deserialize it in a different process and get the right answer. That means no external closures; the lambda must work only with what it creates or is given as a parameter.
Linq2NH 1.0, IIRC, also chokes when using members of the class that are not mapped, so if, for instance, you have a read-only calculated property like a special weighted or rolling average, you must map it to a DB column in order to reference it in the lambda (or recreate the logic in the lambda). This is because the expression tree will eventually be boiled down into SQL (through one of NH's intermediates; in 2.x it's ICriteria, in 3.x it's HQL) and if NH cannot take an expression and convert it 1:1 into a SQL expression that will evaluate successfully, it's just not going to work.
There is one special case: Linq2NH, IIRC, is smart enough to turn an IList.Contains() expression into an IN clause. The list must be defined within the lambda (like new[]{"1","2"}.Contains(m.ID)).
The blog post from Ayende is from May this year. A lot of things changed.
The NHiberante. Linq 1.0 linq provider is deprecated since about a year because of the new linq provider in the NHibernate Trunk. The new linq provider is not completely finished yet, but already very complete and usable for much more than the old linq provider. Things that do not work with the new linq provider are considered bugs and will be solved some day when reported.
You can use skip and take with the old and new linq provider. The current list of known issues can be found on NHibernate Jira. Other issues are unknown and all other features are already supported.

Resources