【问题标题】:Ternary operator in LINQ where clauseLINQ where 子句中的三元运算符
【发布时间】:2013-05-20 11:57:43
【问题描述】:

我正在使用 linq 来连接多个表并编写复杂的查询。这里当我将'0'作为任何参数时,即CategoryIdGameIdLimitVariantId,这意味着用户已经从界面中选择了“全部”。

我的Sql查询,当我传递的参数值大于'0'是:

select * from dbo.GameCombinations gc
inner join dbo.StakeBuyInByStakeCategories sbsc
on sbsc.StakeBuyInByStakeCategoryId = gc.StakeBuyInByStakeCategoryId
inner join dbo.GameTables gt
on gc.GameCombinationId = gt.GameCombinationId
where gc.CurrencyId=1 and gc.GameTypeId=2
and sbsc.StakeBuyInId=gt.BuyIn
and gc.CategoryId=4
and gc.GameId=7
and gc.LimitVariantId=23
and gc.StakeCategoryId in (3,5,6)

当我将 CategoryId 传递为 0 时,My Sql 查询将是:

select * from dbo.GameCombinations gc
inner join dbo.StakeBuyInByStakeCategories sbsc
on sbsc.StakeBuyInByStakeCategoryId = gc.StakeBuyInByStakeCategoryId
inner join dbo.GameTables gt
on gc.GameCombinationId = gt.GameCombinationId
where gc.CurrencyId=1 and gc.GameTypeId=2
and sbsc.StakeBuyInId=gt.BuyIn
--and gc.CategoryId=4
and gc.GameId=7
and gc.LimitVariantId=23
and gc.StakeCategoryId in (3,5,6)

所以我不需要在 where 子句中包含这些字段。为此,我编写了以下 LINQ:

ProviderDB db = new ProviderDB();
try
{
    IQueryable<dynamic> query;

    if (StakeCategoryIdsByStakeBuyIn != null)
    {
        query = (from gc in db.GameCombinations.Where(x => x.CurrencyId == CurrencyId && x.GameTypeId == GameTypeId
                            && CategoryId <= 0 ? true : x.CategoryId == CategoryId
                            && GameId <= 0 ? true : x.GameId == GameId
                            && LimitVariantId <= 0 ? true : x.LimitVariantId == LimitVariantId
                            && StakeCategoryIdsByStakeBuyIn.Contains(x.StakeCategoryId)
                        )
                 join sbsc in db.StakeBuyInByStakeCategories
                 on gc.StakeBuyInByStakeCategoryId equals sbsc.StakeBuyInByStakeCategoryId
                 join gt in db.GameTables
                 on gc.GameCombinationId equals gt.GameCombinationId
                 join gx in db.Games
                 on gc.GameId equals gx.GameId into joined
                 from gx in joined.DefaultIfEmpty()
                 where gt.BuyIn == sbsc.StakeBuyInId
                 select new
                 {
                     GameTableId = gt.GameTableId,
                     Description = gt.Description,
                     BuyIn = gt.BuyIn,
                     Table = gx.GameName,
                     MaxAllowPlayer = gt.MaxAllowPlayer
                 }).Distinct();
    }
    else
    {
        query = (from gc in db.GameCombinations.Where(x => x.CurrencyId == CurrencyId && x.GameTypeId == GameTypeId
                              && CategoryId == 0 ? true : x.CategoryId == CategoryId
                              && GameId == 0 ? true : x.GameId == GameId
                              && LimitVariantId == 0 ? true : x.LimitVariantId == LimitVariantId
                              && StakeCategoryIdsByStakeBuyIn == null
                        )
                 join sbsc in db.StakeBuyInByStakeCategories
                 on gc.StakeBuyInByStakeCategoryId equals sbsc.StakeBuyInByStakeCategoryId
                 join gt in db.GameTables
                 on gc.GameCombinationId equals gt.GameCombinationId
                 join sb in db.StakeBuyIns
                 on gt.BuyIn equals sb.StakeBuyInId
                 join gx in db.Games
                 on gc.GameId equals gx.GameId into joined
                 from gx in joined.DefaultIfEmpty()
                 where gt.BuyIn == sbsc.StakeBuyInId
                 select new
                 {
                     GameTableId = gt.GameTableId,
                     Description = gt.Description,
                     BuyIn = sb.StakeBuyInValue,
                     Table = gx.GameName,
                     MaxAllowPlayer = gt.MaxAllowPlayer
                 }).Distinct();
    }

但这将返回我数据库中的所有字段。那么任何人都可以帮助我在 LINQ 中使用三元条件编写这些查询,以返回我过滤字段的记录吗?

【问题讨论】:

  • 您能详细说明您的要求吗?
  • 三元运算符是否会使其更具可读性?

标签: c# linq sql-server-2008


【解决方案1】:

使用 Linq to SQL(通常使用 LINQ),您可以通过编程方式添加 Where 条件,例如:

var query = db.GameCombinations.Where(x => x.CurrencyId == CurrencyId && x.GameTypeId == GameTypeId);

if (CategoryId > 0)
{
    query = query.Where(x => x.CategoryId == CategoryId);
}

等等。

此外,最好使用“类型推断”(使用var 关键字)而不是dynamicdynamic 不会得到智能感知

[编辑] Linq to SQL 提供程序将在转换为 SQL 时对所有 Where 条件进行分组

【讨论】:

  • 谢谢它对我有帮助。
【解决方案2】:

您仍然可以在 SQL 中执行此查询,尝试类似:

select * from dbo.GameCombinations gc
inner join dbo.StakeBuyInByStakeCategories sbsc
on sbsc.StakeBuyInByStakeCategoryId = gc.StakeBuyInByStakeCategoryId
inner join dbo.GameTables gt
on gc.GameCombinationId = gt.GameCombinationId
where gc.CurrencyId=1 and gc.GameTypeId=2
and sbsc.StakeBuyInId=gt.BuyIn
and (0 = categoryParameter OR gc.CategoryId=categoryParameter) //Pass 0 to take all categories
and gc.GameId=7
and gc.LimitVariantId=23
and gc.StakeCategoryId in (3,5,6)

编辑:

对其余参数执行相同操作:

ProviderDB db = new ProviderDB();

                try
                {
                    IQueryable<dynamic> query;

                    if (StakeCategoryIdsByStakeBuyIn != null)
                    {
                        query = (from gc in db.GameCombinations.Where(x => x.CurrencyId == CurrencyId && x.GameTypeId == GameTypeId
                                            && (CategoryId == 0 || x.CategoryId == CategoryId)
                                            && (GameId == 0 || x.GameId == GameId)
                                            && (LimitVariantId == 0 || x.LimitVariantId == LimitVariantId)
                                            && StakeCategoryIdsByStakeBuyIn.Contains(x.StakeCategoryId)
                                        )
                                 join sbsc in db.StakeBuyInByStakeCategories
                                 on gc.StakeBuyInByStakeCategoryId equals sbsc.StakeBuyInByStakeCategoryId
                                 join gt in db.GameTables
                                 on gc.GameCombinationId equals gt.GameCombinationId
                                 join gx in db.Games
                                 on gc.GameId equals gx.GameId into joined
                                 from gx in joined.DefaultIfEmpty()
                                 where gt.BuyIn == sbsc.StakeBuyInId
                                 select new
                                 {
                                     GameTableId = gt.GameTableId,
                                     Description = gt.Description,
                                     BuyIn = gt.BuyIn,
                                     Table = gx.GameName,
                                     MaxAllowPlayer = gt.MaxAllowPlayer
                                 }).Distinct();
                    }
          }

【讨论】:

  • 谢谢。但我需要在 linq 中查询。
  • 使用与上述查询相同的原理。尝试将CategoryId == 0 ? true : x.CategoryId == CategoryId 替换为(CategoryId == 0 || x.CategoryId == CategoryId)。其他参数也是
  • @noobob, +1, 0 可能不是正确的“其他”值,它可能是null,但这个原则非常有效。
  • @MichaelPerrenoud 0 是他提到的参数,当他想跳过过滤时,他会明确发送。
  • @noobob 你能告诉我我的查询中的整个 LINQ 查询意味着我需要在我的 linq 查询中放置“(CategoryId == 0 || x.CategoryId == CategoryId)”吗?跨度>
【解决方案3】:

您的示例非常复杂,但本质上您是在使用 linq 构建查询。

var someIQueryableInProgress = ... ;

if (categoryId != 0)
{
    someIQueryableInProgress = someIQueryableInProgress
        .Where(s => s.categoryId = categoryId)
}

然后评估您的所有条件何时适用,并让提供者为您完成工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-10
    • 1970-01-01
    • 2016-06-18
    • 2016-06-04
    • 1970-01-01
    • 1970-01-01
    • 2014-06-15
    相关资源
    最近更新 更多