左加入Linq并将变量用于其他连接

时间:2011-07-13 10:22:52

标签: c# linq left-join

当我在Linq for DataSet中使用左连接时,我遇到错误“值不能为null。参数名称行”。

以下是数据和linq查询。

  • DataRowCollection - 项目(列 - Item_id,SKU,数量)
  • DataRowCollection - 促销(Columns - Item_id,Promotion_Id)
  • DataRowCollection - components(Columns - Component_id,Promotion_id)
  • DataRowCollection - 金额(列 - Component_id,Amount_Text,货币)

        var q = 
            from Item in items
            join promotion in promotions
                on Item.Field<int>("Item_id") equals promotion.Field<int?>("Item_id") into promo
            from promotion in promo.DefaultIfEmpty()
            join disccomponent in components
                on promotion.Field<int>("Promotion_Id") equals disccomponent.Field<int?>("Promotion_Id")
            join discamounts in amounts
                on disccomponent.Field<int>("Component_id") equals discamounts.Field<int?>("Component_id")
            where disccomponent.Field<string>("Type") == "Principal"
            select new
            {
                SKU = Item.Field<string>("SKU"),
                Quantity = Item.Field<string>("Quantity"),
                DiscountAmount = discamounts.Field<string>("Amount_Text"),
                DiscountCurrency = discamounts.Field<string>("currency")
            };

我需要得到以下内容:

  • 有折扣的商品的SKU,数量和折扣详情
  • SKU,数量没有任何折扣的物品

当所有项目都有折扣时,代码在没有左外连接的情况下工作,但如果任何项目没有任何折扣,它会跳过该项目,因此我不得不使用左外连接。

非常感谢任何帮助。如果需要澄清,请告诉我。

提前致谢。

3 个答案:

答案 0 :(得分:0)

我认为您正在尝试访问null discamounts上的属性。也许你的精选新版应该看起来像这样......

select new
{
    SKU = Item.Field<string>("SKU"),
    Quantity = Item.Field<string>("Quantity"),
    DiscountAmount = discamounts == null ? "" : discamounts.Field<string>("Amount_Text"),
    DiscountCurrency = discamounts == null ? "" : discamounts.Field<string>("currency")
};

答案 1 :(得分:0)

使用into为您的联接命名并在其上使用DefaultIfEmpty。这样的事情(查看语句中的最后joinfrom表达式)

var q = 
    from Item in items
    join promotion in promotions
        on Item.Field<int>("Item_id") equals promotion.Field<int?>("Item_id") into promo
    from promotion in promo.DefaultIfEmpty()
    join disccomponent in components
        on promotion.Field<int>("Promotion_Id") equals disccomponent.Field<int?>("Promotion_Id")
    join discamounts in amounts
        on disccomponent.Field<int>("Component_id") equals discamounts.Field<int?>("Component_id") into DiscamountJoin
    from discamount in DiscamountJoin.DefaultIfEmpty()
    where disccomponent.Field<string>("Type") == "Principal"
    select new
    {
        SKU = Item.Field<string>("SKU"),
        Quantity = Item.Field<string>("Quantity"),
        DiscountAmount = discamount.Field<string>("Amount_Text"),
        DiscountCurrency = discamount.Field<string>("currency")
    };

答案 2 :(得分:0)

感谢大家的帮助。我通过将它分成下面两个不同的linq查询来完成这项工作。

第一个查询获取var

中的促销数据
        var promoData =
                from promotion in promotions
                join component in components
                    on promotion.Field<int>("Promotion_Id") equals component.Field<int?>("Promotion_Id")
                join amount in amounts
                    on component.Field<int>("Component_id") equals amount.Field<int?>("Component_id")
                where component.Field<string>("Type") == "Principal"
                select new
                {
                    Item_id = promotion.Field<int?>("Item_id"),
                    Promotion_id = promotion.Field<int>("Promotion_Id"),
                    DiscountAmount = amount == null ? "" : amount.Field<string>("Amount_Text"),
                    DiscountCurrency = amount == null ? "" : amount.Field<string>("currency")
                };

第二个查询使用促销var来简化查询并获得结果

        var q = 
            from Item in items
            join promotion in promoData
                on Item.Field<int>("Item_id") equals promotion.Item_id into promo
                from promoJoin in promo.DefaultIfEmpty()
            select new
            {
                SKU = Item.Field<string>("SKU"),
                Quantity = Item.Field<string>("Quantity"),
                DiscountAmount = promoJoin != null ? promoJoin.DiscountAmount : "0",
                DiscountCurrency = promoJoin != null ? promoJoin.DiscountCurrency : ""
            };

这种方法非常有效,无论是否有促销活动,我都可以获得所有项目。我仍在考虑是否可以在单个查询中执行相同操作:) 现在标记为一个答案,如果有人想出其他更好的方法将标记。