【问题标题】:Entity Framework: How to query a number of related tables in a database making a single trip实体框架:如何一次查询数据库中的多个相关表
【发布时间】:2018-03-05 20:51:10
【问题描述】:

我有一个查询目前太慢了。 我正在尝试在主页上搜索一个代码(一个字符串),它将为用户带来相关信息。 例如。用户可以从主页搜索代码,这将在 Job、Work Phase、Wbs、Work Element、EA、Jobcard 和 Estimate 中搜索代码并返回相关信息。 当我相信可以一次完成时,我会多次访问数据库来收集我需要的数据。 我有许多链接的表: 合同、工作、工作阶段、Wbss、工程活动、工作卡和估算。 合同有一份工作清单, 作业有一个工作阶段列表, 工作阶段有一个 Wbss 等列表

有更快的方法吗?

public Result Handle(Query query)
{                   
    query.Code = query.Code ?? string.Empty;

    var result = new Result();

    //result.SetParametersFromPagedQuery(query);
    result.Items = new List<Item>();

    if (query.SearchPerformed)
    {
        var contracts = _db.Contracts.AsEnumerable().Where(x => x.Code == query.Code);

        result.Items = result.Items.Concat(contracts.Select(x => new Item()
        {
            Code = x.Code,
            Id = x.Id,
            Name = x.Name,
            Type = MainPageSearchEnum.Contract,
            ContractName = x.Name,
            Url = string.Format("Admin/Contract/Edit/{0}", x.Id)
        })).ToList();


        var jobs = _db.Jobs.AsEnumerable().Where(x => x.Code == query.Code);

        result.Items = result.Items.Concat(jobs.Select(x => new Item()
        {
            Code = x.Code,
            Id = x.Id,
            Name = x.Name,
            ContractName = x.Contract.Name,
            Type = MainPageSearchEnum.Job,
            Url = string.Format("Admin/Job/Edit/{0}", x.Id)
        })).ToList();

        //var workPhases = _db.WorkPhases.AsEnumerable().Where(x => x.ContractPhase.Code.ToLower() == query.Code.ToLower());
        var workPhases = _db.WorkPhases.AsEnumerable().Where(x => x.ContractPhase.Code == query.Code);

        result.Items = result.Items.Concat(workPhases.Select(x => new Item()
        {
            Code = x.ContractPhase.Code,
            Id = x.Id,
            Name = x.ContractPhase.Name,
            Type = MainPageSearchEnum.WorkPhase,
            Url = string.Format("Admin/WorkPhase/Edit/{0}", x.Id)
        })).ToList();

        var wbss = _db.WBSs.AsEnumerable().Where(x => x.Code == query.Code);

        result.Items = result.Items.Concat(wbss.Select(x => new Item()
        {
            Code = x.Code,
            Id = x.Id,
            Name = x.Name,
            Type = MainPageSearchEnum.WBS,
            Url = string.Format("Admin/WBS/Edit/{0}", x.Id)
        })).ToList();

        var eas = _db.EngineeringActivities.AsEnumerable().Where(x => x.Code == query.Code);

        result.Items = result.Items.Concat(eas.Select(x => new Item()
        {
            Code = x.Code,
            Id = x.Id,
            Name = x.Name,
            Type = MainPageSearchEnum.EA,
            Url = string.Format("Admin/EngineeringActivity/Edit/{0}", x.Id)
        })).ToList();

        var jcs = _db.Jobcards.AsEnumerable().Where(x => x.Code == query.Code);

        result.Items = result.Items.Concat(jcs.Select(x => new Item()
        {
            Code = x.Code,
            Id = x.Id,
            Name = x.Name,
            Type = MainPageSearchEnum.EA,
            Url = string.Format("Admin/JobCard/Edit/{0}", x.Id)
        })).ToList();

        var estimates = _db.Estimates.AsEnumerable().Where(x => x.Code == query.Code);

        result.Items = result.Items.Concat(estimates.Select(x => new Item()
        {
            Code = x.Code,
            Id = x.Id,
            Name = x.Name,
            Type = MainPageSearchEnum.Estimate,
            Url = string.Format("Estimation/Estimate/Edit/{0}", x.Id)
        })).ToList();

    }

    return result;
}

【问题讨论】:

    标签: c# mysql entity-framework


    【解决方案1】:

    免责声明:我是项目的所有者Entity Framework Plus

    此库具有 Query Future 功能,允许在一次往返中批量处理多个查询。

    例子:

    // using Z.EntityFramework.Plus; // Don't forget to include this.
    var ctx = new EntitiesContext();
    
    // CREATE a pending list of future queries
    var futureCountries = ctx.Countries.Where(x => x.IsActive).Future();
    var futureStates = ctx.States.Where(x => x.IsActive).Future();
    
    // TRIGGER all pending queries in one database round trip
    // SELECT * FROM Country WHERE IsActive = true;
    // SELECT * FROM State WHERE IsActive = true
    var countries = futureCountries.ToList();
    
    // futureStates is already resolved and contains the result
    var states = futureStates.ToList();
    

    维基:EF+ Query Future

    【讨论】:

      【解决方案2】:

      您尝试过Union / UnionAll 运算符吗?

      其目的与您的愿望完全一样 - 将来自不同来源的相同数据组合在一起。

      此外,由于 deferred execution 的概念,您的查询只会在您实际迭代结果时执行(或调用执行此操作的方法,例如 - .ToList()

      var contractsQuery = _db.Contracts.AsEnumerable().Where(x => x.Code == query.Code).Select(x=>new {Code=x.Code, Id=x.Id, ...});
      var jobsQuery = _db.Jobs.AsEnumerable().Where(x => x.Code == query.Code).Select(x=>new{Code=x.Code, Id=x.Id, ...});
      var workPhasesQuery = _db.WorkPhases.AsEnumerable().Where(x => x.ContractPhase.Code == query.Code).Select(x=>new{Code=x.Code, Id=x.Id, ...});
          // and so on
      var combinedQuery = contractsQuery.UnionAll(jobsQuery).UnionAll(workPhasesQuery ).UnionAll(...
      var result = combinedQuery.ToList();
      

      类似的问题是Union in linq entity framework
      另一个代码示例可以找到here

      请注意,这与 T-SQL union 中操作数据的概念完全相同,并且在幕后您将使用 union 运算符获得 sql 查询

      【讨论】:

      • 您好 Ironstone13,感谢您的回复。我是这个地区的新手。但这不会像我仍然必须一次查询每个表一样慢吗?
      • @user3597791,好吧,这样您实际上只在var result = combinedQuery.ToList() 行中运行查询 - 了解延迟执行 docs.microsoft.com/en-us/dotnet/framework/data/adonet/ef/… 的概念
      • @user3597791,不客气!顺便说一句,您可以使用 Sql Server 分析器或 EF 查询日志记录 msdn.microsoft.com/en-us/library/dn469464(v=vs.113).aspx 验证正在执行的查询
      • @user3597791,显然,由您来判断最佳答案;-) 但我的看法是,我的答案是最精确、最详细且带有相关代码示例的 :-) 如果您有任何问题'不见了,或者有些东西不工作 - 让我知道
      【解决方案3】:

      是的,肯定有一种查询多个表的方法。您可以使用Include() 方法扩展进行查询。例如:

      var examplelist = _db.Contracts.(v => v.id == "someid" && v.name == "anotherfilter").Include("theOtherTablesName").ToList();
      

      您可以通过这种方式添加任意数量的表格。这是推荐的方法。

      您也可以使用UnionAll() 方法,但您必须为此单独定义查询

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-13
        • 1970-01-01
        • 1970-01-01
        • 2022-12-01
        相关资源
        最近更新 更多