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

问题描述 投票:1回答:3

我的查询目前太慢了。我正在尝试在主页面上搜索代码(字符串),这将为用户提供相关信息。例如。用户可以从主页面搜索代码,这将在Job,Work Phase,Wbs,Work Element,EA,Jobcard和Estimate中搜索代码并返回相关信息。我在数据库中进行了多次访问以收集我需要的数据,当我相信它只能在一个数据库中完成时。我有许多链接的表:合同,工作,工作阶段,Wbss,工程活动,Jobcards和估计。合同有一个Jobs列表,Jobs有一个Workphases列表,Workphases有一个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
3个回答
0
投票

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

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

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

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


2
投票

免责声明:我是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


1
投票

你试过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查询

© www.soinside.com 2019 - 2024. All rights reserved.