I have the following database structure:
USER <--> [user_client] <--> CLIENT <--> [client_application] <--> APPLICATION
USER, CLIENT and APPLICATION tables contain unique keys. user_client and client_application are many-to-many tables to map USERs to CLIENTs and CLIENTs to APPs.
I am using MVC5 / C#. The many-to-many tables are hidden in my Model by the Entity Framework.
What I want to achieve is the following: for a given USER, which has a list of CLIENTs, get the combined list of the distinct APPLICATIONs that all his CLIENTs have.
Could you please help with the logic and the Linq query (preferably in fluent syntax if possible)? Is it possible to do it in a single query without looping through the list of clients?
Thank you in advance.
Reda
Not sure it matches your schema but what about
user.clients.SelectMany(c => c.applications).Distinct()
The key is to use SelectMany instead of Select which will give you a IEnuerable<Application> instead of a IEnumerable<IEnumerable<Application>>
var user = context.Users.Where(u => u.Id == 1).Single();
var applications = user.Clients
.SelectMany(c => c.Application)
.GroupBy(a = a.Id)
.Select(a => a.First());
I want to collaborate to this question, not providing an exact solution, but additional information.
I applied #tafia answer to my own problem, but with a slight modification to the SelectMany method. I replaced it with just Select.
File selectedFile = _unitOfWork.FileRepository.GetById(idFile)
selectedFile.FilePaper.Select(c => c.Paper).Distinct().ToList()
You can read about the difference between Select and SelectMany, here.
I applied my modified solution on the following group of tables:
Though your table seems to be different:
I'm not sure if that solution proposed by #tafia works there.
PS. If you want to make the middle tables appear in EF, a possible "fix" is adding a primary key to them (id).
Related
Good day,
I have a diagram with 5 tables.
As you can see, I have a category table and medical studies with details.
Also two similar tables : OtherStudy and OtherMedicalStudyDetails.
These tables also have some foreing keys that come from other tables that are not included in this diagram.
For the sake of simplicity I provided a database diagram that does not look good but makes it simpler to explain my problem (somebody could tell me I should use just the medicalStudy and medicalStudy details tables and do not use the other two, but I would like to keep the diagram like this please).
What I am trying to do is, after adding (using c# entityframework) a medicalStudy with its MedicalStudyDetails, compare both detail tables and bring a list of all "OtherStudy" where (MedicalStudyDetails.FK_otherTable==OtherMedicalStudyDetails.FK_otherTable&& MedicalStudyDetails.FK_anotherTable==OtherMedicalStudyDetails.FK_anotherTable).
. Note that this compairson should be done foreach MedicalStudyDetails added.
is there a way to bring the mentioned list using a sintax like this?
var otherStudy= _dbContext.MedicalStudyDetails.Include(...)
.Where(...)
.ToList();
Wouldn't you need a multiple clause inner join to achive this??
from msd in _dbContext.MedicalStudyDetails
join omsd in _dbContext.OtherMedicalStudyDetails on
new {msd.FK_otherTable, msd.FK_anotherTable} equals new { omsd.FK_otherTable, omsd.FK_anotherTable}
where ...
select ...
Please advise,, ALL the resources I've perused , books, videos tutorials none have what I would assume to be a simple, common scenario.
-----What is the Most efficient and standard way of querying through bridge tables with Link To Entities-----
I'm trying to to a query with Linq To Entities.I is my understanding that LinqToSQL is deprecated even if informally..
I have a standard
one to many (bridge table)
and the bridge table many to one for the final table
and lastly a specific key for the original table
If it helps there's a User table atop this mess with a one to many user to roles
Tables:
User, ( Not in the Query I have a specific KeyId for this table for the where clause),
Role,
&
RolePermission, ( Bridge / map whatever you want to call it, it has FK's for Role & Permission )
[unfortunately it has other cols or this wouldn't be so stressful. I.E. its not
abstracted in the entity framework its actually present],
& Permission.
Summary I want every permission for every role for this user, User ID lets say 5
I have a list of roles per user so (to start) I intended on feeding this query the role ID and calling it multiple times ,,, appending its results to a list 4Ea RoleId This is assuredly not ideal
Ideal would be to utilize the UserID & RoleID in a single query...
How do you do Multiple Inner Joins in Linq to Entities
This link above claimed that you can just pull his off by requesting all the tables involved without specifically joining them the PK-FK fields ?!?!?! Say What ??!
This is Just Peuedo code folks I've typed up several dozen attempts at this scenario
parameter p_RoleId --- potential version of this could get RoleId's per passed in UserID ideally
List<Permissions> listToReturn = new List<Permissions>();
var result=(from p in context.Permissions
from rp in m.RolePermissions
where m.roleID = p_RoleId
listToReturn result.ToList();
I really just want to know how to correctly hook these tables together and specify some where clause.
Two table examples are everywhere.. but there or four when you have a bridge table I found nothing
try this
var result = (from p in context.Permissions
join px in m.RolePermissions on p.roleID equals px.roleID
select p);
Well you can definitely do what you are writing in your pseudo code. After all what you do is an implied join. But it might not be very efficient.
You are essentially doing a
select <something> from Permissions , RolePermissions where permissions.id = permissionsRoles.id;
And you do not need a foreign key for that. However in your case you have many to many
//with the assumption that you have a
//navigation property between roles and rolepermissions in your model
var result = connection.Permissions
.Where(i => i.Id == RolePermissionsid)that
.SelectMany(i => i.RolePermissions).ToList();
Is this what you want?
var result=(from p in context.Permissions
join rp in m.RolePermissions on p.RoleId equals rp.RoleId
select p)
I’d like to consult about a problem I have faced. I've started working on a project with a very difficult database: many tables in the DB don’t have primary keys or have multiple PKs, so I can't add correct associations for all entities in my edmx. However, for some entities it’s possible and I managed to do so. Thus, I have two entities with an association between them: Vulner and VulnerDescription. And I have a "bad" connection table for Vulners called VulnerObjectTie (with a mental FK: VulnerObjectTie.Vulner = Vulner.Id), which I can’t add correct associations to. So, I decided to do add the following LinqtoEntities query:
var vulerIdList = from vulner in _businessModel.DataModel.VulverSet.Include("Descriptions")
join objectVulnerTie in _businessModel.DataModel.ObjectVulnerTieSet on vulner.Id equals objectVulnerTie.Vulner
where softwareId.Contains(objectVulnerTie.SecurityObject)
select vulner;
where description is Navigation Property for an association with the VulnerDescription table. The query works, but it does not load the Descriptions property. However, if I remove the join operator, then Descriptions are loaded correctly.
The most obvious solution for this problem is to divide one query into the next two queries:
var vulerIdList = from vulner in _businessModel.DataModel.VulverSet
join objectVulnerTie in _businessModel.DataModel.ObjectVulnerTieSet on vulner.Id equals objectVulnerTie.Vulner
where softwareId.Contains(objectVulnerTie.SecurityObject)
select vulner.Id;
var query = from vulner in _businessModel.DataModel.VulverSet.Include("Descriptions")
where vulerIdList.Contains(vulner.Id)
select vulner;
But I think it looks ugly. Can anyone suggest a more simple solution for this problem, or is it just a special feature of EF4??
thankyouplease :))
It's a known 'feature' or limitation, depending on how you look at it. Here's an interesting discussion on the topic, I'm sure there are more references to find: http://social.msdn.microsoft.com/forums/en-US/adodotnetentityframework/thread/d700becd-fb4e-40cd-a334-9b129344edc9/
The problem here is that EF is not very well suited for "bad databases". EF (and especially all automation tools like model wizard) expects clear and correct database design.
Include is not supported in queries using custom joins or projections. Not supported in this case means that it is completely omitted.
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.
Long time lurker, first time posting, and newly learning EF4 and MVC3.
I need help making sure I'm using the correct data loading strategy in this case as well as some help finalizing some details of the query. I'm currently using the eager loading approach outlined here for somewhat of a "dashboard" view that requires a small amount of data from about 10 tables (all have FK relationships).
var query = from l in db.Leagues
.Include("Sport")
.Include("LeagueContacts")
.Include("LeagueContacts.User")
.Include("LeagueContacts.User.UserContactDatas")
.Include("LeagueEvents")
.Include("LeagueEvents.Event")
.Include("Seasons")
.Include("Seasons.Divisions")
.Include("Seasons.Divisions.Teams")
.Where(l => l.URLPart.Equals(leagueName))
select (l);
model = (Models.League) query.First();
However, I need to do some additional filtering, sorting, and shaping of the data that I haven't been able to work out. Here are my chief needs/concerns from this point:
Several child objects still need additional filtering but I haven't been able to figure out the syntax or best approach yet. Example: "TOP 3 LeagueEvents.Event WHERE StartDate >= getdate() ORDER BY LeagueEvents.Event.StartDate"
I need to sort some of the fields. Examples: ORDERBY Seasons.StartDate, LeagueEvents.Event.StartDate, and LeagueContacts.User.SortOrder, etc.
I'm already very concerned about the overall size of the SQL generated by this query and the number of joins and am thinking that I may need a different data loading approach alltogether.(Explicit loading? Multiple QueryObjects? POCO?)
Any input, direction, or advice on how to resolve these remaining needs as well as ensuring the best performance is greatly appreciated.
Your concern about size of the query and size of the result set are tangible.
As #BrokenGlass mentioned EF doesn't allow you doing filtering or ordering on includes. If you want to order or filter relations you must use projection either to anonymous type or custom (non mapped) type:
var query = db.Leagues
.Where(l => l.URLPart.Equals(leagueName))
.Select(l => new
{
League = l,
Events = l.LeagueEvents.Where(...)
.OrderBy(...)
.Take(3)
.Select(e => e.Event)
...
});
Unfortunately EF doesn't allow to selectively load related entities using its navigation properties, it will always load all Foos if you specify Include("Foo").
You will have to do a join on each of the related entities using your Where() clauses as filters where they apply.