简体   繁体   English

实体框架:如何查询数据库中的多个相关表进行单次旅行

[英]Entity Framework: How to query a number of related tables in a database making a single trip

I have a query that is currently far too slow. 我的查询目前太慢了。 I am trying to search a Code (a string) on the main page that will bring the user the relevant info. 我正在尝试在主页面上搜索代码(字符串),这将为用户提供相关信息。 Eg. 例如。 The user can search a code from the main page and this will search for the code in Job, Work Phase, Wbs, Work Element, EA, Jobcard and Estimate and return the relevant info. 用户可以从主页面搜索代码,这将在Job,Work Phase,Wbs,Work Element,EA,Jobcard和Estimate中搜索代码并返回相关信息。 I make a number of trips to the database to collect the data i need when I believe it can be done in just one. 我在数据库中进行了多次访问以收集我需要的数据,当我相信它只能在一个数据库中完成时。 I have a number of tables that are all linked: Contracts, Jobs, WorkPhases, Wbss, Engineering Activities, Jobcards and Estimates. 我有许多链接的表:合同,工作,工作阶段,Wbss,工程活动,Jobcards和估计。 Contracts have a list of Jobs, Jobs have a list of Workphases, Workphases have a list of Wbss etc 合同有一个Jobs列表,Jobs有一个Workphases列表,Workphases有一个Wbss列表等

Is there a quicker way to do this? 有更快的方法吗?

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;
}

Disclaimer : I'm the owner of the project Entity Framework Plus 免责声明 :我是项目Entity Framework Plus的所有者

This library has a Query Future feature which allows batching multiple queries in a single roundtrip. 该库具有Query Future功能,允许在单个往返中批处理多个查询。

Example: 例:

// 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();

Wiki: EF+ Query Future 维基: EF +查询未来

Have you tried the Union / UnionAll operator? 您是否尝试过Union / UnionAll运营商?

It's purpose is exactly like you wish - combine the identical data from different sources. 它的目的与您希望的完全一样 - 结合来自不同来源的相同数据。

Furthermore due to the concept of deferred execution your query will only be executed when you actually iterate over the result (or call a method that does that, for example - .ToList() 此外,由于延迟执行的概念,您的查询将仅在您实际迭代结果时执行(或调用执行该操作的方法,例如 - .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();

A similar question is Union in linq entity framework 类似的问题是linq实体框架中的Union
Another code sample can be found here 可在此处找到另一个代码示例

Please notice that this is exactly the same concept of manipulating data as in T-SQL union , and under the covers you will get an sql query using a union operator 请注意,这与在T-SQL 联合中操作数据的概念完全相同,并且在封面下,您将使用union运算符获得sql查询

Yes there most certainly is a way to query multiple tables. 是的,肯定有一种查询多个表的方法。 You can use the Include() method extension for your query. 您可以为查询使用Include()方法扩展名。 for instance: 例如:

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

You can include as many tables as you like this way. 您可以通过这种方式包含任意数量的表。 This is the recommended method. 这是推荐的方法。

You can also use the UnionAll() method but you'd have to define your queries separately for this 您也可以使用UnionAll()方法,但您必须为此单独定义查询

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

相关问题 如何使实体框架在一次数据库访问中插入条目 - How to make entity framework insert entries in one trip to database 如何更新实体框架中的相关表? - How to update related tables in entity-framework? 实体框架-如何返回没有相关对象的单个实体 - Entity Framework - How to return single entity without related objects 如何 select 使用实体框架在相关表中重复最多的记录 - How to select the most repeating records in related tables with Entity Framework 使用实体框架,如何创建查询以从数据库中获取所有表的列名 - Using Entity Framework, how to create a query which will fetch the column names of all tables from a database 在实体框架中通过 id 查询相关实体 - Query a related entity by id in Entity Framework 使用实体框架的表中的相关数据 - Related data in tables using Entity Framework 实体框架相关表获取和保存数据 - Entity Framework Related Tables Get and Save Data 实体框架-保存模型与相关表 - Entity Framework-Saving models with related tables 使用带有实体框架和 LINQ 的单个数据库查询搜索多个字符串 - Searching for multiple strings using single database query with entity framework and LINQ
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM