Can IQueryable<> only contain instructions (in the form of expression tree) on how to get the initial sequence, but not - linq

1)
public class Query<T> : IQueryable<T> ...
{
...
public IEnumerator<T> GetEnumerator()
{
return((IEnumerable<T>)this.provider.Execute(this.expression)).GetEnumerator();
}
}
Query<string> someQuery = new Query<string>();
someQuery.Expression holds the expression tree associated with this particular instance of IQueryable and thus describes how to retrieve the initial sequence of items. In the following example initialSet variable actually contains a sequence of strings:
string[] initialSet = { };
var results1 = from x in initialSet
where ...
select ...;
a) Can someQuery also contain a sequence of strings, or can it only contain instructions ( in the form of expression tree ) on how to get this initial sequence of strings from some DB?
b) I assume that even if someQuery actually contains an initial sequence of strings, it is of no use to Where and Select operators, since they won't ever operate on this sequence of strings, but instead their job is only to build queries or request queries to be executed ( by calling IQueryProvider.Execute)? And for this reason someQuery must always contain an expression tree describing how too get the initial sequence of strings, even if someQuery already contains this initial sequence?
Thank you
EDIT:
c) The way I understood your post is that query provider may contain information about describing the table or at least describing particular DB rows which initial query needs to retrieve. But I didn't interpret your answer as saying that query provider may also contain actual elements required by this initial query ( someQuery in our example )?
d) Regardless, I assume even if query provider maintains actual elements, it can only maintain them for initial query? Thus if we apply Linq-to-entity or Linq-to-Sql operators on that initial query, I assume provider will have to query the database. As such, if my assumption are correct then answer to b) would be even if query does contain actual elements, when we call Where on someQuery ( someQuery.Where ),query provider will have to retrieve results from a DB, even if this query provider already contains all the elements of someQuery?
e) I only started learning Linq-to-entities, so my question may be too general, but how does EF handle all of this? In other words, when does ObjectSet<T> returned by some EF API ( such as ObjectContext ), contain actual elements and when does it ( if ever ) contain only logic for retrieving elements from some data source (such as DB)?
f) Also, even if ObjectSet<T> ( returned by say ObjectSet ) does contain actual elements, I assume if we apply Where operator on it ( ObjectSet<T>.Where ), query provider will always have to retrieve results from the DB?

a) You wouldn't normally create a Query<T> yourself - a query provider would. It can choose to include whatever information it wants. It's most likely to just contain the information about what table it's associated with though.
b) That's entirely up to the query provider. As you saw in the other question, the query provider may end up recognizing when it's reached a Query<T> - so it could know to ask the Query<T> for its strings, if that was appropriate.
c) The query provider wouldn't usually contain data itself - but it could do. It's up to the provider.
d) The query provider may notice that it's within a transaction, and that it's already executed a similar context in the query - it may be able to answer the query from within its cache. It's up to the query provider.
e, f) No idea, I've never used Entity Framework in anger.
The answer to almost all of your questions around this is topic is "it's up to the query provider". For details about a particular query provider, you should read the documentation for that provider. That should explain when it will make queries etc. It's unclear what you're really trying to get out of these questions - but if you're after a full implementation to study, there are plenty of open source LINQ providers around. You might want to look at NHibernate for example.

Related

How to implement conditional relationship clause in cypher for Spring Neo4j query?

I have a cypher query called from Java (Spring Neo4j) that I'm using, which works.
The basic query is straightfoward - it asks what nodes lead to another node.
The gist of the challenge is that there are a set (of three) items - contributor, tag, and source - that the query might need to filter its results by.
Two of these - tag and source - bring with them a relationship that needs to be tested. But if these are not provided, then that relationship does not need to be tested.
Neo-browser warns me that the query I'm using it will be inefficient, for probably obvious reasons:
#Query("MATCH (p:BoardPosition)<-[:PARENT]-(n:BoardPosition)<-[:PARENT*0..]-(c:BoardPosition),
(t:Tag), (s:JosekiSource) WHERE
id(p)={TargetID} AND
({ContributorID} IS NULL or c.contributor = {ContributorID}) AND
({TagID} IS NULL or ((c)-->(t) AND id(t) = {TagID}) ) AND
({SourceID} IS NULL or ((c)-->(s) AND id(s) = {SourceID}) )
RETURN DISTINCT n"
)
List<BoardPosition> findFilteredVariations(#Param("TargetID") Long targetId,
#Param("ContributorID") Long contributorId,
#Param("TagID") Long tagId,
#Param("SourceID") Long sourceId);
(Java multi-line query string catenation removed from code for clarity)
It would appear that this would be more efficient if the conditional inclusion of the relationship-test could be in the MATCH clause itself. But that does not appear possible.
Is there some in-cypher way I can improve the efficiency of this?
FWIW: the Neo4j browser warning is:
This query builds a cartesian product between disconnected patterns.
If a part of a query contains multiple disconnected patterns, this
will build a cartesian product between all those parts. This may
produce a large amount of data and slow down query processing.

Clean way to write this query

I'm looking for a clean way to write this Linq query.
Basically I have a collection of objects with id's, then using nhibernate and Linq, I need to check if the nhibernate entity has a subclass collection where all id's in object collection exist in the nhibernate subclass collection.
If there was just one item this would work:
var objectImCheckingAgainst = ... //irrelevant
where Obj.SubObj.Any(a => a.id == objectImCheckingAgainst.Id)
Now I want to instead somehow pass a list of objectImCheckingAgainst and return true only if the Obj.SubObj collection contains all items in list of objectImCheckingAgainst based on Id.
I like to use GroupJoin for this.
return objectImCheckingAgainst.GroupJoin(Obj.SubObj,
a => a.Id,
b => b.id,
(a, b) => b.Any())
.All(c => c);
I believe this query should be more or less self-explanatory, but essentially, this joins the two collections using their respective ids as keys, then groups those results. Then for each of those groupings, it determines whether any matches exist. Finally, it ensures that all groupings had matches.
A useful alternative that I sometimes use is .Count() == 1 instead of the .Any(). Obviously, the difference there is whether you want to support multiple elements with the same id matching. From your description, it sounded like that either doesn't matter or is enforced by another means. But that's an easy swap, either way.
An important concept in GroupJoin that I know is relevant, but may or may not be obvious, is that the first enumerable (which is to say, the first argument to the extension method, or objectImCheckingAgainst in this example) will have all its elements included in the result, but the second one may or may not. It's not like Join, where the ordering is irrelevant. If you're used to SQL, these are the elementary beginnings of a LEFT OUTER JOIN.
Another way you could accomplish this, somewhat more simply but not as efficiently, would be to simply nest the queries:
return objectImCheckingAgainst.All(c => Obj.SubObj.Any(x => x.id == c.Id));
I say this because it's pretty similar to the example you provided.
I don't have any experience with NHibernate, but I know many ORMs (I believe EF included) will map this to SQL, so efficiency may or may not be a concern. But in general, I like to write LINQ as close to par as I can so it works as well in memory as against a database, so I'd go with the first one I mentioned.
I'm not well versed in LINQ-to-NHibernate but when using LINQ against any SQL backen it's always important to keep an eye on the generated SQL. I think this where clause...
where Obj.SubObj.All(a => idList.Contains(a.id))
...will produce the best SQL (having an IN statement).
idList is a list of Ids extracted from the list of objectImCheckingAgainst objects.

How to build a custom key for matching two queries, using Linq-To-Entities

I want to match in-memory entities to data from DB-tables and return a new in-memory DTO with a subset of that matched information. Now, matching involves two columns, thus I am building a new key on the fly. This works, as long as I execute the queries before building the keys, effectively using Linq-To-Objects for the matching.
When not executing the query right away, I receive a runtime exception as described by this MSDN article.
Here is my code and data model, simplified. I have
Rooms (as IEnumerable<Room>, already in memory)
Areas (as IEnumerable<Room>, already in memory)
Alarms (from the DB, as IQueryable from the context)
Alarms are tied to Areas and LocationIds. Rooms can have multiple Areas, and have one LocationId.
I want to build a set of Alarms occurred in a set of Rooms. This involves matching the Alarm's Area and LocationsId to each Room's LocationId and the Areas.
from area in allAreas
let alarmKey = area.AreaName + area.Room.LocationId //AreaName is String, LocationId is integer
//....
However, this line involves a not supported cast form int to String. How to create the key?
If you don't mind a number of leading spaces in LocationId you can do
let alarmKey = area.AreaName +
SqlFunctions.StringConvert((double)area.Room.LocationId)
SqlFunctions is in System.Data.Objects.SqlClient.

Trying to execute a WHERE IN: Invalid 'where' condition. An entity member is invoking an invalid property or method

I'm trying to get a list of cases whose AccountID is found in a previous list.
The error occurs on the last line of the following:
// Gets the list of permissions for the current contact
var perms = ServiceContext.GetCaseAccessByContact(Contact).Cast<Adx_caseaccess>();
// Get the list of account IDs from the permissions list
var customerIDs = perms.Select(p => p.adx_accountid).Distinct();
// Get the list of cases that belong to any account whose ID is in the `customerID` list
var openCases = (from c in ServiceContext.IncidentSet where customerIDs.Contains(c.AccountId) select c).ToList();
I'm not sure what the "invalid property" is the error is talking about. The code compiles, I just get the error at runtime.
The problem is the CRM Linq Provider. It doesn't support all of the available options that the Linq-to-objects provider offers. In this case, the CRM does not support the Enumerable.Contains() method.
where:
The left side of the clause must be an attribute name and the
right side of the clause must be a value. You cannot set the left side
to a constant. Both the sides of the clause cannot be constants.
Supports the String functions Contains, StartsWith, EndsWith, and
Equals.
You can work around this in one of two ways:
Rework your query to use a more natural join.
If a join is not possible, you can use Dynamic Linq to generate a list of OR clauses on each item in customerIDs. This would function similarly to Enumerable.Contains.
See my answer or the accepted answer to the question "How to get all the birthdays of today?" for two separate ways to accomplish this.

Linq-to-sql Not Contains or Not in?

I'm building a poll widget. I've 2 tables, call them Polls and PollsCompleted. I need to do a linq query to get all the Polls that do not exist for a given user in PollsCompleted.
I have the following sets:
For Polls
Where Active == True
For PollsCompleted
Where UserId == ThisUserId
Where PollId = Polls.Id
Now I need to get all Polls that do not exist in PollsCompleted. I need an example for this using either a single or multiple queries. I've tried to break it down into 2 queries.
Basically, I've 2 IQueryables of type T and T1. I want to take all T's where T.ID does not exist in T1.ParentId.
T.Where(x => ! T1.Select(y => y.ParentID).Contains(x.ID))
In Linq you often work from the bottom up. Here we first get a collection of all the parentIDs in T1 -- the T1.Select(...) part. Then we create a where clause that selects all of the Ts whose IDs are not contained in that set.
Note that the result is a query. To materialize it, use ToList() or similar on the statement above.
Use Except. That will work in this case.
For your reference Enumerable.Except Method

Resources