Reach Related Entities' Attributes - asp.net-mvc-3

I get an entity list by following:
var riscregions = db.RiscEntranceDetails.OrderBy(r => r.RiscEntranceID).Include(r => r.RiscEntrance).Include(r => r.RiscRegion);
However, I need to reach more deeply related entities attributes, such as:
<td>#item.RiscEntrance.ID</td>
<td>#item.RiscEntrance.Personnel.Name</td>
<td>#item.RiscEntrance.EntranceDateTime</td>
<td>#item.RiscEntrance.ShiftWork.ShiftGroup.TextID</td>
How can I reach those? Any suggestions including linq, or some other workarounds such as extensions and helpers are greatly appreciated.

You can do this:
var riscregions = db.RiscEntranceDetails
.OrderBy(r => r.RiscEntranceID)
.Include(r => r.RiscEntrance)
.Include(r => r.RiscEntrance.Personnel)
.Include(r => r.RiscEntrance.ShiftWork.ShiftGroup)
You need to use Select in your Include expression only if you need to select children of a collection.

http://msdn.microsoft.com/en-us/data/jj574232.aspx
See eagerly loading multiple levels. You can use .Select() in your .Include() lambda.

Related

Need some help on a somewhat complex LINQ query

I have this query that does what I want which is to return true if any of the materials is comparable in the material groups list.
mgroup.MaterialGroups.Select(x => x.Materials
.Any(m => Convert.ToBoolean(m.Comparable)))
.Any(x => x.Equals(true))
What I would like to add to this query is to also include this one.
mgroup.Materials.Any(m => Convert.ToBoolean(m.Comparable));
How can I combine mgroup and it's materialgroups together in the query so I can select both of their Materials? Thanks.
EDIT - After fighting with LINQ for awhile I broke down and just combined as
mgroup.Materials.Any(m => Convert.ToBoolean(m.Comparable) ||
mgroup.MaterialGroups.Select(x => x.Materials
.Any(c => Convert.ToBoolean(c.Comparable)))
.Any(x => x.Equals(true)))
It works as expected but it's horribly long and it's embedded in an Asp.net MVC view to makes things even worse. If anyone can simplify this that would be amazing.
P.S.- If you are wondering why I added the extra .Any(x => x.Equals(true) at the end it's because without it the query returns an IEnumerable of bools instead of bool.
IEnumerable<Material> allMaterials =
mgroup.Materials.Concat(
mgroup.MaterialGroups.SelectMany(group => group.Materials));
bool result = allMaterials.Any(m => Convert.ToBoolean(m.Comparable));

preserving the order of returning entities when using .Contains(Id)

I want to hydrate a collection of entities by passing in a List of Ids and also preserve the order.
Another SO answer https://stackoverflow.com/a/15187081/1059911 suggested this approach to hydrating the entities which works great
var entities = db.MyEntities.Where(e => myListOfIds.Contains(e.ID)).ToList();
however the order of entities in the collection is different from the order of Ids
Is there a way to preserve the order?
May be that helps:
var entities = db.MyEntities
.Where(e => myListOfIds.Contains(e.ID))
.OrderBy(e => myListOfIds.IndexOf(e.ID)).ToList();
EDIT
JohnnyHK clarified that this will not work with LINQ to Entities. For this to work you need to order IEnumerable instead of IQueryable, since IQueryProvider don't know how to deal with local list IndexOf method when it sends query to server. But after AsEnumerable() OrderBy method deals with local data. So you can do this:
var entities = db.MyEntities
.Where(e => myListOfIds.Contains(e.ID))
.AsEnumerable()
.OrderBy(e => myListOfIds.IndexOf(e.ID)).ToList();
Entity Framework contains a subset of all of the LINQ commands so you won't have all the commands that LINQ to Objects has.
The following approach should give you your list of MyEntities in the same order as supplied by myListOfIds:
var entities = myListOfIds.Join(db.MyEntities, m => m, e => e.ID, (m,e) => e)
.ToList();

LINQ to compare item in one list to any item in another

I wonder, if someone could help me...
Is there a LINQ query that will return a bool, if any item from one IList<> is contained int another IList<>.
These IList<>'s are object and I need to compare one a single property of the object, the "Name" property in this case?
Is there a LINQ query that can do this? If so could someone show me the correct implementation?
Thank you
Well you could project both lists:
if (list1.Select(x => x.Name)
.Intersect(list2.Select(x => x.Name))
.Any())
Is that what you're after?
I think this should do it:
bool matchExists = list1.Any(a1 => list2.Any(a2 => a1.Name == a2.Name));
Another one for your options:
List1.Where(l => List2.Select(s => s.Name).Contains(l.Name)).Any();
I usually use it like below:
List<UserInfo> userUpd = nd.Where(x => !rd.Any(y => y.Identifier.Equals(x.Identifier))).ToList();

Finding n-Most Popular Using Linq

How should I structure a Linq query to return a List or Ienumerable of the most popular Tags in my db (I am using EF4.1 by the way).
Currently I have:
var tagsListing = db.Tags
.GroupBy(q => q.Name)
.OrderByDescending(gp => gp.Count())
.Take(5)
.Select();
I think I am part of the way there, but I am unsure of how to structure the Select statement...
Your Select call could look like this:
.Select(gp => gp.Key)
That will give you an IEnumerable<string> of your most popular tags (assuming that Name is a string).
Assuming you want the name and the count, just:
.Select(g => new { Name = g.Key, Count = g.Count() });
EDIT: If you want the complete tags as well, you could use:
.Select(g => new { Tags = g, Count = g.Count() })
which would give you a sequence of groups of tags, all with the same name within a group. Or you might only want the first tag within each group, e.g.
.Select(g => g.First())
It's not clear what a Tag consists of, or what exactly you want in the results.
You've written a perfectly workable query and do not need to call .Select
IQueryable<IGrouping<string, Tag>> tagsListing = db.Tags
.GroupBy(q => q.Name)
.OrderByDescending(gp => gp.Count())
.Take(5);
List<IGrouping<string, Tag>> results = tagListing.ToList();
You probably want to select the names like this:
.Select(gp => gp.Key);

How to return distinct rows from and Entity with related Entities

I have an Entity that has an association to other Entities (related entities). I'm trying to return distinct rows from the primary entity which needs to include the data from the related entity so I can use one the related entity's properties downstream.
Below is the statement I'm using but it is not returning any rows. What's the best way to do this?
Below is my code.
return context.UserDisplays.Include("CurrentJob").Where(d => d.UserName == userName).GroupBy(d => d.CurrentJob.JobNo).Select(g => g.FirstOrDefault()).ToList();
Any help would be greatly appreciated!
Edit - For ComplexProperty
I believe once you do a GroupBy all Include methods are ignored. So you will need to iterate the list and call the LoadProperty method on each item. It should look something like this
var list = context.UserDisplays
.Where(d => d.UserName == userName)
.GroupBy(d => d.CurrentJob.JobNo)
.Select(g => g.FirstOrDefault()).ToList();
foreach(var item in list)
{
context.LoadProperty(item, "CurrentJob");
}
return list;
Resource Link
Check out the Distinct (Set Operators) section in this article
http://msdn.microsoft.com/en-us/vcsharp/aa336746
Are you asking for the Distinct UserDisplays? or the Distinct User or the Disticnt Jobs?
I would try say something like
var object = (from userDisplay in context.UserDisplays.Include("CurrentJob")
.Where userDisplay.UserName == userName
Select userDisplay).Distinct();
(sorry, im going off of my VB style but it should be about the same...)

Resources