有条件加入Linq

log*_*eyg 5 c# linq

有没有办法逐步/有条件地将联接添加到查询?我正在为客户端创建自定义报告工具,并且向客户端提供了他/她可以选择查询的对象的列表。查询中将始终有一个基础对象(“ FWOBid”)。

因此,例如,如果客户选择对象“ FWOBid”,“ FWOItem”和“ FWOSellingOption”,则需要这样做:

var query = from fb in fwoBids

// if "FWOSellingOption", add this join
join so in sellingOptions on fb.Id equals so.BidId

// if "FWOItem", add this join
join i in fwoItems on fb.Id equals i.FWOBidSection.BidId

// select "FWOBid", "FWOItem", and "FWOSellingOption" (everything user has selected)
select new { FWOBid = fb, FWOSellingOption = so, FWOItem = i };
Run Code Online (Sandbox Code Playgroud)

诀窍是客户可以选择大约6个彼此相关的对象,从而产生许多不同的联接组合。如果可能的话,我想避免对它们进行硬编码。

Mic*_*der 6

一种选择是结合左连接进行一些自定义连接。

一个体面的 TSQL 后端在始终使用所有连接的性能方面不应该有任何缺点,因为如果条件始终为假,优化器只会删除连接。但是这个应该检查一下。

bool joinA = true;
bool joinB = false;
bool joinC = true;

var query = from fb in fwoBids
            join so in sellingOptions on new { fb.Id, Select = true } equals new { Id = so.BidId, Select = joinA } into js
            from so in js.DefaultIfEmpty()
            join i in fwoItems on new { fb.Id, Select = true } equals new { Id = i.FWOBidSection.BidId, Select = joinB } into ji
            from i in ji.DefaultIfEmpty()
            join c in itemsC on new { fb.Id, Select = true } equals new { Id = c.BidId, Select = joinC }
            select new
            {
                FWOBid = fb,
                FWOSellingOption = so,
                FWOItem = i,
                ItemC = c
            };            
Run Code Online (Sandbox Code Playgroud)


Ale*_*ris 6

在 Linq 查询语法中,这是不可能的,或者查看其他答案几乎不可读。没有多少可读性,但另一种可能性是使用扩展方法(某种伪代码):

        bool condition1;
        bool condition2;

        List<Bid> bids = new List<Bid>();
        List<SellingOption> sellingOptions = new List<SellingOption>();
        List<Item> items = new List<Item>();

        var result = bids.Select(x => new {bid = x, sellingOption = (SellingOption)null, item = (Item)null});

        if (condition1)
            result = result.Join(
                sellingOptions,
                x => x.bid.Id,
                x => x.BidId,
                (x, sellingOption) => new { x.bid, sellingOption, item = (Item)null });

        if (condition2)
            result = result.Join(
                items,
                x => x.bid.Id,
                x => x.BidId,
                (x, item) => new { x.bid, x.sellingOption, item });
Run Code Online (Sandbox Code Playgroud)

只需将其视为一种概念即可。这与 Peter Duniho 所做的基本相同。

问题是,如果您不想在没有必要的情况下立即加入所有选项,那么它看起来不会那么好。也许您现在应该尝试加入所有成员,而不必担心性能。你有没有测量过它可能有多慢或多快?把它想象成“我现在不需要它!”。如果性能确实是一个问题,那么您可以采取行动。但如果不是,并且您不知道您是否从未尝试过,那么将其保留为您提到的六个连接。