LINQ中的.Take方法是否有通配符?

时间:2013-06-03 15:00:45

标签: c# linq entity-framework

我正在尝试使用LINQ创建一个方法,该方法将从数据库中获取X ammount产品,因此我正在使用.TAKE方法。

问题是,在我需要采取所有产品的情况下,是否有一个我可以提供的通配符.TAKE或其他一些方法可以为我带来数据库中的所有产品?

此外,如果我执行.TAKE(50)并且数据库中只有10个产品会发生什么? 我的代码看起来像:

var ratingsToPick = context.RatingAndProducts
    .ToList()
    .OrderByDescending(c => c.WeightedRating)
    .Take(pAmmount);

2 个答案:

答案 0 :(得分:6)

您可以根据您的旗帜将其分成单独的电话:

IEnumerable<RatingAndProducts> ratingsToPick = context.RatingAndProducts
    .OrderByDescending(c => c.WeightedRating);

if (!takeAll)
    ratingsToPick = ratingsToPick.Take(pAmmount);

var results = ratingsToPick.ToList();

如果您不包含Take,那么它只会包含所有内容。

请注意,您可能需要将原始查询键入IEnumerable<MyType>,因为OrderByDescending会返回IOrderedEnumerable,并且无法从Take来电重新分配。 (或者你可以根据你的实际代码简单地解决这个问题)

另外,正如@ Rene147指出的那样,您应该将ToList移到最后,否则每次都会从数据库中检索所有项目OrderByDescending和{ {1}}然后实际操作内存中的Take个对象而不是将其作为数据库查询执行,我认为这是无意的。


关于您的第二个问题,如果您执行List<>但只有10个条目可用。这可能取决于您的数据库提供程序,但在我的体验中,它们往往足够智能,不会抛出异常,只会为您提供任意数量的项目。 (我建议你进行快速测试,以确定你的具体情况)

答案 1 :(得分:2)

您当前的解决方案始终从数据库中获取所有产品。因为您正在呼叫ToList()。从数据库加载所有产品后,您将在内存中占用前N个。为了有条件地加载前N个产品,您需要构建查询

int? countToTake = 50;
var ratingsToPick = context.RatingAndProducts
                           .OrderByDescending(c => c.WeightedRating);

// conditionally take only first results
if (countToTake.HasValue)
   ratingsToPick = ratingsToPick.Take(countToTake.Value);

var result = ratingsToPick.ToList(); // execute query