【问题标题】:load related enties without using include in Entity Framework Core加载相关实体而不使用 Entity Framework Core 中的包含
【发布时间】:2018-06-26 11:36:04
【问题描述】:

我打算在不使用 C#/实体框架中的包含的情况下加载相关实体。 在我的示例中,我使用左连接来加载所有问题选项,这些选项仅在我在 LINQ 查询的 select 语句中明确表示时才显示。我的问题是如何确保它加载相关实体而不在 LINQ 查询中的 select 中定义相关实体。

数据模型

public class QuestionDataModel : BasicDataModel
{
    public QuestionDataModel()
    {            
        QuestionOptions = new HashSet<QuestionOptionDataModel>();

    }

    public Guid Id { get; set; }

    public virtual ICollection<QuestionOptionDataModel> QuestionOptions { get; set; }

}

LINQ 查询

var q1 = (
           from question in Context.Questions
            join options in Context.QuestionOptions on question.Id equals options.QuestionId into qo
             where question.ConsultationId == Guid.Parse("10324003-0012-4D99-95D8-7E7189CA3888")
                select new
                  {
                    question
                    //,qo  // it only loads questionOption if qo is here, I need to do without that, since it is collection property in QuestionDataModel class
                  }
           ).ToList();

【问题讨论】:

  • 你想加载实体包含还是不包含?
  • 我想加载没有包含的实体!
  • 如果您使用的是EF Core 2.1,您可以启用延迟加载,当您显式调用它时将加载相关实体。参考这个docs.microsoft.com/en-us/ef/core/querying/…

标签: linq entity-framework-core


【解决方案1】:

数据库会话中较慢的元素之一是将选定数据从数据库管理系统传输到您的进程。明智的做法是不要向您的流程发送比您实际计划使用的更多的数据。

显然你有一个Questions序列,其中每个Question有零个或多个QuestionOptions,每个QuestionOption恰好属于一个Question,即QuestionId等于QuestionOption.QuestionId。一个简单的一对多,在QuestionId 中有一个外键。

如果您要获取 ID == 4 的 Question 及其一万个 QuestionOptions,您知道每个 QuestionOption 都会有一个值为 4 的 QuestionId。您将转移该值4 到 10,000 次,而您可能甚至不会使用它,因为您已经知道它等于 Question.Id

解决方案是:仅在计划更新数据库项目时使用 Include。 在所有其他情况下,请使用 Select。 仅选择您实际计划使用的属性。

在方法语法中(如果你愿意,也可以使用类似的查询语法)

var result = context.Questions.Join(context.QuestionOptions, // join Questions and QuestionOptions
    question => question.Id,                      // from every Question take the Id
    questionOption => questionOption.QuestionId,  // from every Option take the QuestionId
    (question, questionOption) => new              // when they match make a new object
    {    // Select only the properties you plan to use:
         Question = new 
         {
             Id = question.Id,
             ... other question properties
         },
         Option = new
         {
             Id = questionOption.Id,
             // not needed: questionOption.QuestionId, it equals Question.Id
             ... other properties you plan to use
         }
    });

仅当您确实打算使用所有获取的元素时才使用ToList。尽可能长时间地保持您的结果为 IQueryable。

如果您希望拥有每个Question with its QuestionOptions,请考虑使用Queryable.GroupBy

var questionsWithTheirOptions = context.Questions
   .GroupJoin(context.QuestionOptions,            // GroupJoin Questions and QuestionOptions
    question => question.Id,                      // from every Question take the Id
    questionOption => questionOption.QuestionId,  // from every Option take the QuestionId
    (question, optionsOfQuestion) => new          // when they match make a new object
    {   // desired Question Properties
        Id = question.Id,
        ...

        // The options of this question:
        Options = optionsOfQuestion.Select(option => new
        {
            Id = questionOption.Id,
            // not needed: questionOption.QuestionId, it equals Question.Id
            ... 
        })
        .ToList()
    });

【讨论】:

  • 非常感谢它对我的思考和方法的帮助...最后一件事... group by 如何帮助加快速度??
  • 分组?你是说GroupJoin?如果一个有 1000 个选项的 Question 是普通连接中的查询,那么 Question 的属性发送了多少次?如果您使用 GroupJoin 提出一个包含 1000 个选项的问题,那会是多少次?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-29
  • 2018-02-27
  • 1970-01-01
  • 2016-10-10
  • 1970-01-01
  • 1970-01-01
  • 2020-08-06
相关资源
最近更新 更多