Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在查询时洗牌产品列表_C#_Linq - Fatal编程技术网

C# 在查询时洗牌产品列表

C# 在查询时洗牌产品列表,c#,linq,C#,Linq,我在数据库中有一个产品和类别表: 产品有以下列: ProductId、ProductName、说明、路径、名称、URL、类别ID、活动 类别具有以下列: CategoryId,CategoryName 我已经编写了一个LINQ语句来查询数据库并获取相关类别的产品。查询工作正常 public IQueryable<Product> GetProducts( [QueryString("id")] int? categoryId,

我在数据库中有一个产品和类别表:

产品有以下列: ProductId、ProductName、说明、路径、名称、URL、类别ID、活动

类别具有以下列: 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;
}
公共IQueryable GetProducts(
[QueryString(“id”)]int?categoryId,
[RouteData]字符串类别名称)
{
var_db=new products.Models.ProductContext();
IQueryable查询=_db.Products;
if(categoryId.HasValue&&categoryId>0)
{
query=query.Where(p=>p.CategoryID==CategoryID);
}
如果(!String.IsNullOrEmpty(categoryName))
{
query=query.Where(p=>
String.Compare(p.Category.CategoryName,
类别名称)==0);
}
返回查询;
}
我有两个疑问:

  • 如何修改此查询以仅选择那些活动=1的产品

  • 目前,该查询根据productId-1、2、3、4、5等,以特定顺序返回行。如何洗牌结果,使结果不以特定顺序返回。它可以是5、2、4、1、3,或者下一次运行3、5、1、4、2等等


  • 要筛选活动产品,只需通过以下方式扩展查询:

    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);
    }
    

    首先,洗牌部分。不能使用
    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;
    } 
    
    公共静态无效交换(参考T x,参考T y)
    {
    var-temp=x;
    x=y;
    y=温度;
    }
    public static T[]RandomShuffle(此IEnumerable源)
    {
    var result=source.ToArray();
    if(result.Length<2)返回结果;
    var random=新的random();
    对于(int i=result.Length-1;i>0;i--)
    {
    int pos=随机。下一个(i+1);
    如果(pos!=i)交换(参考结果[pos],参考结果[i]);
    }
    返回结果;
    } 
    
    现在,您的功能:

    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;
    }
    
    公共IQueryable GetProducts(
    [QueryString(“id”)]int?categoryId,
    [RouteData]字符串类别名称)
    {
    var_db=new products.Models.ProductContext();
    IQueryable查询=_db.Products;
    query=query.Where(p=>p.Active==1);//第一个问题
    if(categoryId.HasValue&&categoryId>0)
    {
    query=query.Where(p=>p.CategoryID==CategoryID);
    }
    如果(!String.IsNullOrEmpty(categoryName))
    {
    query=query.Where(p=>
    String.Compare(p.Category.CategoryName,
    类别名称)==0);
    }
    返回查询;
    }
    

    您可以保持这种方式(IMO更好),并在需要时在调用端应用shuffle,如
    GetProducts(..).randomsuffle()
    。或者,如果您坚持在内部执行,只需将最后一行更改为
    returnquery.RandomShuffle().AsQueryable()

    是否返回
    IQueryable
    一项要求,例如,是否允许将方法的签名更改为返回
    IEnumerable
    ?如果没有,是否允许在方法内部具体化查询?如果我将其更改为IEnumerable,它将如何受益/解决我的需求?受益-否,解决-是(第二部分-随机化)。看看目前的答案。我认为没有一种方法可以使用
    IQueryable
    进行随机化。这就是为什么我们需要具体化(即执行)查询,然后随机化。当然,我们总是可以将enumerable变为queryable,但这扼杀了针对db的queryable的整个概念。最好保留签名,只添加
    p.Active==1
    标准。通过这种方式,您可以使用函数并应用“Count()”、添加条件或选择等,然后创建另一个执行随机化的通用方法。听起来不错?谢谢,我会试试的。在每个类别中,我有大约30种产品。如何确定退货数量?只需使用
    query.Count()
    。但这将具体化结果,因此它将执行查询。只有提交了
    类别ID
    时,活动产品的扩展才会起作用。为什么不把它变成一个单独的
    ,Where
    ?@Rawling你能解释一下如何把它变成一个单独的Where吗?@IWantToLearn-Ivan的答案在线评论了
    //第一个问题
    。我不确定发生了什么。我正在使用像这样的产品。我可以调试并看到行正在被洗牌,但当它出现在ListView上时,它们看起来是有序的。我不熟悉该控件,我猜它可能在内部应用了一些排序。
    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;
    }