查询时随机播放产品列表

时间:2015-09-03 07:02:05

标签: c# linq

我在数据库中有一个Products和Category表:

产品包含以下列: ProductId,ProductName,Description,Path,Name,URL,CategoryId,Active

类别包含以下列: CategoryId,CategoryName

我编写了一个LINQ语句来查询数据库并获取相关类别的产品。查询工作正常。

public IQueryable<Product> GetProducts(
                     [QueryString("id")] int? categoryId,
                     [RouteData] string categoryName)
{
    var _db = new products.Models.ProductContext();
    IQueryable<Product> query = _db.Products;

    if (categoryId.HasValue && categoryId > 0)
    {
        query = query.Where(p => p.CategoryID == categoryId);
    }

    if (!String.IsNullOrEmpty(categoryName))
    {
        query = query.Where(p =>
                            String.Compare(p.Category.CategoryName,
                            categoryName) == 0);
    }
    return query;
}

我有两个疑问:

  1. 如何修改此查询以仅选择那些Active = 1的产品。

  2. 目前,查询以特定顺序返回行,我认为该行基于productId - 1,2,3,4,5等。如何将结果混洗,以便不按特定顺序返回结果。它可能是5,2,4,1,3或下一次运行3,5,1,4,2等等。

2 个答案:

答案 0 :(得分:0)

要过滤Active产品,只需按以下方式扩展查询:

query = query.Where(p => p.CategoryID == categoryId && p.Active == 1);

要改变结果,您必须自己编写代码。它可能是这样的:

var shuffledList = new List<Product>();
var originalList = query.ToList();
var random = new Random();

while (originalList.Count() > 0) {
    var pick = random.Next(0, originalList.Count());
    var product = originalList[pick];
    shuffledList.Add(product);
    originalList.Remove(product);
}

shuffledList将按随机顺序包含您的商品。但是你会记住一些内存,因为你的内存中有两倍的产品。

我刚遇到的另一种可能性是:

var random = new Random();    
query = query.OrderBy(product => random.Next());

答案 1 :(得分:0)

首先,洗牌部分。它不能用IQueryable来完成,所以最好引入一个通用的扩展方法是一些常见的地方:

public static void Swap<T>(ref T x, ref T y)
{
    var temp = x;
    x = y;
    y = temp;
}
public static T[] RandomShuffle<T>(this IEnumerable<T> source)
{
    var result = source.ToArray();
    if (result.Length < 2) return result;
    var random = new Random();
    for (int i = result.Length - 1; i > 0; i--)
    {
        int pos = random.Next(i + 1);
        if (pos != i) Swap(ref result[pos], ref result[i]);
    }
    return result;
} 

现在你的功能:

public IQueryable<Product> GetProducts(
                     [QueryString("id")] int? categoryId,
                     [RouteData] string categoryName)
{
    var _db = new products.Models.ProductContext();
    IQueryable<Product> query = _db.Products;
    query = query.Where(p => p.Active == 1); // the first question
    if (categoryId.HasValue && categoryId > 0)
    {
        query = query.Where(p => p.CategoryID == categoryId);
    }
    if (!String.IsNullOrEmpty(categoryName))
    {
        query = query.Where(p =>
                            String.Compare(p.Category.CategoryName,
                            categoryName) == 0);
    }
    return query;
}

您可以保持这种方式(IMO更好)并在您需要该行为时在呼叫方应用随机播放,例如GetProducts(....).RandomShuffle()。或者,如果您坚持在内部进行,只需将最后一行更改为return query.RandomShuffle().AsQueryable();