I have SQL Server table structure like below
Id title nextID
-------------------
1 w 2
2 x 3
3 y 4
4 z null
How can I get the result in the form of LinkedList by using entity framework?
Like This
Id:1
tile:w
nextId:2
nextNode => Id:2
tile:x
nextId:3
nextNode => Id:3
tile:y
nextId:4
nextNode => Id:4
tile:z
nextId:null
nextNode:null
Typically, you would need to get the relevant rows out first, and then form the linked list yourself. Assuming that the data is more complex in reality (i.e. there exist other rows that aren't in the same chain), this makes it harder to query - you'd either need to perform multiple round-trips (as you iteratively discover the next link in the chain), or you'd need to write your own recursive CTE (or a while loop in SQL, if you prefer) to fetch the entire chain in one go. In either scenario, EF isn't really going to go out of its way to help you do this - you're going to have to do that yourself. And by the time you're doing that, I wonder whether it might make more sense (or at least: sense) to switch to hierarchyid as the implementation; as I understand it: this should allow you to query everything in the same hierarchy in a single query (noting that in your case, each level in the hierarchy would only have at most a single child)
Related
I found an interesting issue in Entity Framework. Check the code bellow. Here i am using Contains() to find all matching Id rows from Table Test1 but when i add same id multiple times it returns only 1 item not duplicating items but i want to get duplicate items too. How can i do this then?
var ids = new List<int>();
ids.Add(1);
ids.Add(1);
var foo = ctx.Test1.Include("Test2").Where(x => ids.Contains(x.Id)).ToList();
YOu can not. You really need to learn the basic of how SQL works and how query works because your question is a fundamental misunderstanding.
when i add same id multiple times it returns only 1 item not duplicating items
Because the table STILL contains only 1 item. if you add the same ID multiple times, why would you expect it to return the row multiple times?
The way it is evaluated is:
Take row
Check whether the ID matches any of the provided list.
Next row.
So, regardless how often you put the ID into the list of approved id's, it OBVIOUSLY will only return one row. You do not get duplicate items because you do not have duplicate items to start with.
Like so often when using anything Ef related, it also helps to intercept and look at the generated SQL and the generated query plan - this at least will make obviously clear that you can not get 2 id's. Contains will be an IN clause, containing the list of values. Like I said above, contains checks for rows, it will not magically duplicate them.
I would suggest making the duplication manually after query - though in 25 years I have never seen this requirement coming up, so I would strongly suggest you check whether what you try to do makes any logical sense from a higher perspective first.
Why should it be the other way? Your EF Contains instruction has in SQL "IN" form:
SELECT
...
FROM ...
WHERE ... IN (1, 1)
I'm using entity framework and building up a linq query so the query is executed at the database to minimize data coming back and the query can have some search criteria which is optional and some ordering which is done every time. I am working with parents and children (the mummy and daddy type). The filter I am trying to implement is for age of the children.
So if I have some data like so...
parent 1
- child[0].Age = 5
- child[1].Age = 10
parent 2
- child[0].Age = 7
- child[1].Age = 23
...and I specify a minimum age of 8, my intended result to display is...
parent 1
- child[1].Age = 10
parent 2
- child[1].Age = 23
...and if I specify a minimum age of 15 I intend to display...
parent 2
- child[1].Age = 23
I can re-create my expected result with this horrible query (which I assume is actually doing more than one query):
var parents = context.Parents;
if(minimumChildAge.HasValue)
{
parents = parents.Where(parent => parent.Children.Any(child => child.Age >= minimumChildAge.Value));
foreach(var parent in parents)
{
parent.Children = parent.Children.Where(child => child.minimumChildAge.Value >= mimumumChildAge);
}
}
parents = parents.OrderBy(x => x.ParentId).Take(50);
So I tried the other method instead...
var query = from parent in context.Parents
select parent;
if (minimumChildAge.HasValue)
query = from parent in query
join child in context.Children
on parent.ParentId equals child.ParentId
where child.Age >= minimumChildAge.Value
select parent;
query = query.OrderBy(x => x.ParentId).Take(50);
When I run this in linqpad the query generated looks good. So my question...
Is this the correct way of doing this? Is there a better way? It seems a bit funny that if I now specified a maximum age that I would be writing the same joins and hoping that entity framework works it out. In addition, how does this impact lazy loading? I expect only the children which match the criteria to be returned. So when I do parent.Children does entity framework know that it just queried these and its working on a filtered collection?
Assuming your context is backed by an entity framework database or similar, then yes, your first option is going to do more than one SQL query. When you begin executing the foreach it will run a SQL query to get the parent (since you've forced enumeration on the query). Then, for each attempt to populate the Children property of a single parent object it will make another database call.
The second form should only produce a single SQL query; it will have a ton of redundant data but it will use JOIN statements to bring back all of the parent and child data in a single SQL call, then enumerate through it and populate the data on the client side as needed.
A rule of thumb I tend to follow is that, if you have fewer than 4 nested tables in your query, try to run it all at once. Both SQL and Entity Framework's query parsers seem to be very, very efficient when producing joins at that level.
If you get much beyond that, the SQL queries that EF can produce may get messy, and SQL itself (assuming MSSQL) gets less effective when you have 5+ joins on a single query. There's no hard and fast limit, because it depends on a number of specific factors, but if I find myself needing very deep nesting I tend to break it up into smaller LINQ queries and recombine them client-side.
(Side note: you can reproduce your second query in method syntax easily enough, since that's what the compiler is going to end up doing anyway, by using the Join method, but the syntax for that can get very complex; I typically go with query syntax for anything more complex then a single method call.)
My database structure is this: an OptiUser belongs to multiple UserGroups through the IdentityMap table, which is a matching table (many to many) with some additional properties attached to it. Each UserGroup has multiple OptiDashboards.
I have a GUID string which identifies a particular user (wlid in this code). I want to get an IEnumerable of all of the OptiDashboards for the user identified by wlid.
Which of these two Linq-to-Entities queries is the most efficient? Do they run the same way on the back-end?
Also, can I shorten option 2's Include statements to just .Include("IdentityMaps.UserGroup.OptiDashboards")?
using (OptiEntities db = new OptiEntities())
{
// option 1
IEnumerable<OptiDashboard> dashboards = db.OptiDashboards
.Where(d => d.UserGroups
.Any(u => u.IdentityMaps
.Any(i => i.OptiUser.WinLiveIDToken == wlid)));
// option 2
OptiUser user = db.OptiUsers
.Include("IdentityMaps")
.Include("IdentityMaps.UserGroup")
.Include("IdentityMaps.UserGroup.OptiDashboards")
.Where(r => r.WinLiveIDToken == wlid).FirstOrDefault();
// then I would get the dashboards through user.IdentityMaps.UserGroup.OptiDashboards
// (through foreach loops...)
}
You may be misunderstanding what the Include function actually does. Option 1 is purely a query syntax which has no effect on what is returned by the entity framework. Option 2, with the Include function instructs the entity framework to Eagerly Fetch the related rows from the database when returns the results of the query.
So option 1 will result in some joins, but the "select" part of the query will be restricted to the OptiDashboards table.
Option 2 will result in joins as well, but in this case it will be returning the results from all the included tables, which obviously is going to introduce more of a performance hit. But at the same time, the results will include all the related entities you need, avoiding the [possible] need for more round-trips to the database.
I think the Include will render as joins an you will the able to access the data from those tables in you user object (Eager Loading the properties).
The Any query will render as exists and not load the user object with info from the other tables.
For best performance if you don't need the additional info use the Any query
As has already been pointed out, the first option would almost certainly perform better, simply because it would be retrieving less information. Besides that, I wanted to point out that you could also write the query this way:
var dashboards =
from u in db.OptiUsers where u.WinLiveIDToken == wlid
from im in u.IdentityMaps
from d in im.UserGroup.OptiDashboards
select d;
I would expect the above to perform similarly to the first option, but you may (or may not) prefer the above form.
I need to have a database that starts with a table called "User" that needs to self reference itself and will have a very deep graph of related objects. It will need to be like the left side of the image below (disregard the right side).
I will also need to traverse through this graph both up and downwards in order to calculate percentages, totals, etc. In other words I'll need to travese the entire graph in some cases.
Is this possible and/or how is it done? Can traversing be done right in the LINQ statement? Examples?
EDIT:
I'm basically trying to create a network marketing scenario and need to calculate each persons earnings.
Examples:
To be able to calulate the total sales for each user under a specific user (so each user would have some sort of revenue coming in).
Calculate the commission at a certain level of the tree (e.g. if the top person had 3 people below them each selling a product for $1 and the commission was 50% then there would be $1.50.)
If I queried the image above (on the left) for "B" I should get "B,H,I,J,N,O"
Hopefully that helps :S
You can't traverse the whole tree using just LINQ in a way that would translate to single SQL query (or a constant count of them). You can do it either with one query for each level or with one query, that is limited to a specific count of levels (but such a query would get really big with many levels).
In T-SQL (I assume you're using MS SQL Server), you can do this using recursive common table expressions. It should be possible to put that into a stored procedure that you can use from LINQ to get the information you actually want.
To sum up, your options are:
Don't use LINQ, just SQL with recursive CTE
Use recursive CTE in a stored procedure from LINQ
Use LINQ, creating one query for each level
Use ugly LINQ query limited to just a few levels
I know this is late, but if you look at Directed Graph algorithms, you can bypass the recursive issues. check out these 2 articles:
http://www.sitepoint.com/hierarchical-data-database/
http://www.codeproject.com/Articles/22824/A-Model-to-Represent-Directed-Acyclic-Graphs-DAG-o
Say I have a dataset such as this:
PersonId | ManagerId | DepartmentId
========================================
1 null 1
2 1 1
3 1 2
4 2 1
and so on.
I am looking for a Linq query which:
Given a ManagerId and a set of
DepartmentIds will give me all
relevant PersonIds. The query should
return all PersonIds under a manager,
all the way down the tree, not just
those immediately under that manager.
Here's what I've tried so far: http://pastebin.com/zF9dq6wj
Thanks!
Chris.
Using Linq, there's no automatic way to do this (that I've ever heard of) without multiple trips to the database. As such, it's really no different than any other recursive call structure and you can chose between recursive method calls, a while with a System.Collections.Queue (or Stack) object for ids, etc. If your backend database is SQL Server 2008 or higher, you can make use of it's recursive query capabilities, but you'll have to call a sproc to do it as Linq won't be able to make the translation itself.
You cant do recursive queries in Linq2SQL or Linq2Entities. I would suggest writing a View with a CTE and add that to your DataContext file.