C# 在查询时洗牌产品列表
我在数据库中有一个产品和类别表: 产品有以下列: ProductId、ProductName、说明、路径、名称、URL、类别ID、活动 类别具有以下列: CategoryId,CategoryName 我已经编写了一个LINQ语句来查询数据库并获取相关类别的产品。查询工作正常C# 在查询时洗牌产品列表,c#,linq,C#,Linq,我在数据库中有一个产品和类别表: 产品有以下列: ProductId、ProductName、说明、路径、名称、URL、类别ID、活动 类别具有以下列: CategoryId,CategoryName 我已经编写了一个LINQ语句来查询数据库并获取相关类别的产品。查询工作正常 public IQueryable<Product> GetProducts( [QueryString("id")] int? categoryId,
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);
}
返回查询;
}
我有两个疑问:
要筛选活动产品,只需通过以下方式扩展查询:
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;
}