简体   繁体   中英

Need to Include() related entities but no option to do so

I'm not sure how else to word the title of this question so let me explain. I have a need to select most of one entity type from my database, using .Include to select it's related entities, but at the same time to only select the entities where the entity identifier is equal to one of the IDs in a string array.

My code as follows:

List<TSRCategory> electives = new List<TSRCategory>();           
foreach (var i in client.Electives.Split('&'))
{
    int id = Int32.Parse(i);
    electives.Add(db.TSRCategories.Find(id));
}

This correctly selects the TSRCategories that are part of the Electives list of IDs, but does not include the related entities. I was using this code:

TSRCategories = db.TSRCategories.Include("Competencies.CompetencySkills").ToList();

but this does not select only the chosen Electives. What I am ideally looking for is something like this:

List<TSRCategory> electives = new List<TSRCategory>();           
foreach (var i in client.Electives.Split('&'))
{
    int id = Int32.Parse(i);
    electives.Add(db.TSRCategories.Find(id));
}
TSRCategories = electives.Include("Competencies.CompetencySkills").ToList();

But of course this can't be done for whatever reason (I don't actually know what to search for online in terms of why this can't be done!). Electives is a string with the & as a delimiter to separate the IDs into an array. TSRCategories contains Competencies which contains CompetencySkills. Is there a way to actually do this efficiently and in few lines?

Try to use this extensions method :

using System.Data.Entity;

from x in db.Z.Include(x => x.Competencies)
              .Include(x => x.Competencies.CompetencySkills)
select a.b.c;

To search by the given list of ids:

int[] ids = new int[0]; // or List<int>
from x in db.Z
where ids.Contains(x.Id)
select a.b.c;

You will find that fetching the associated ids one by one will result in poor query performance. You can fetch them all in one go by first projecting a list of all the needed ids (I've assumed the key name ElectiveId here):

var electiveIds = client.Electives.Split('&')
                        .Select(i => Int32.Parse(i))
                        .ToArray();
var electives = db.TSRCategories
                  .Include(t => t.Competencies.Select(c => c.CompetencySkills))
                  .Where(tsr => electiveIds.Contains(tsr.ElectiveId))
                  .ToList();

But one thing to mention is that the storage of your ids in a single string field joined by a delimiter violates database normalization. Instead, you should create a new junction table, eg ClientElectives which link the Electives associated with a Client in normalized fashion (ClientId, ElectiveId) . This will also simplify your EF retrieval code.

Edit

According to the examples in the documentation , I should be using .Select for depth specification of the eager loading (not .SelectMany or other extension methods).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM