简体   繁体   English

需要包括()相关实体,但没有其他选择

[英]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. 我需要使用.include从数据库中选择一种实体类型中的大多数,以选择它的相关实体,但同时只选择实体标识符等于字符串数组中ID之一的实体。

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. 这将正确选择属于“ ID的选修课”列表中的“ TSR类别”,但不包括相关实体。 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. Electives是一个以&为分隔符的字符串,用于将ID分隔为一个数组。 TSRCategories contains Competencies which contains CompetencySkills. TSRCategories包含包含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: 要通过给定的ID列表进行搜索,请执行以下操作:

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. 您会发现,一一读取关联的ID将导致查询性能下降。 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): 您可以通过首先投影所有所需ID的列表来一次性获取所有信息(我在这里假设键名称为ElectiveId ):

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. 但是要提及的一件事是,将ids存储在由定界符连接的单个字符串字段中会违反数据库规范化。 Instead, you should create a new junction table, eg ClientElectives which link the Electives associated with a Client in normalized fashion (ClientId, ElectiveId) . 相反,您应该创建一个新的联结表,例如ClientElectives ,它以规范化的方式链接与客户关联的选修课(ClientId, ElectiveId) This will also simplify your EF retrieval code. 这也将简化您的EF检索代码。

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). 根据文档中的示例,我应该使用.Select来指定急切加载的深度(而不是.SelectMany或其他扩展方法)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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