![](/img/trans.png)
[英]Optimize finding Min/Max value using Entity Framework LINQ only
[英]Finding Min and Max using LINQ
我正在尝试创建一个 LINQ 查询,允许用户从我网页上的下拉列表中选择“最小值”或“最大值”。 如果用户选择 Min 它将显示具有最低报价的记录(报价来自名为 rentals 的数据库表)
我对 .Min() 和 .Max() 没有任何好感。 我不确定如何解决这个问题,因此我们将不胜感激。
这是我的 if 语句,用于确定用户在下拉框中选择的选项:
namespace CarGarageSales.Pages.Queries
{
[BindProperties]
public class Query3Model : PageModel
{
private readonly CarGarageSales.Data.CarGarageSalesContext _context;
public IList<Rental> Rental { get; set; }
[BindProperty(SupportsGet = true)]
public int UserInput { get; set; }
public Query3Model(CarGarageSales.Data.CarGarageSalesContext context)
{
_context = context;
}
public async Task OnGetAsync()
{
if (UserInput == 0)
{
var Rentals = (from s in _context.Rentals
select s);
Rental = await Rentals.ToListAsync();
}
else if (UserInput == 1)
{
var Rentals = (from s in _context.Rentals
select s).Min();
}
else
{
var Rentals = (from s in _context.Rentals
select s.Quote).Max();
}
}
}
}
这是我的 HTML 部分:
@page
@model CarGarageSales.Pages.Queries.Query3Model
@{
ViewData["Title"] = "Query3";
}
<h2>Query3</h2>
<form>
<p>
Min or Max?:<select asp-for="UserInput">
<option></option>
<option>Min</option>
<option>Max</option>
</select>
<input type="submit" value="Search" />
</p>
</form>
<p class="Text">Here is the record for the Rentals you requested!</p>
<table class="table Text">
<thead>
<tr>
<th>
@Html.DisplayNameFor(model => model.Rental[0].RentalID)
</th>
<th>
@Html.DisplayNameFor(model => model.Rental[0].Price)
</th>
<th>
@Html.DisplayNameFor(model => model.Rental[0].Duration)
</th>
<th>
@Html.DisplayNameFor(model => model.Rental[0].Quote)
</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.Rental)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.RentalID)
</td>
<td>
@Html.DisplayFor(modelItem => item.Price)
</td>
<td>
@Html.DisplayFor(modelItem => item.Duration)
</td>
<td>
@Html.DisplayFor(modelItem => item.Quote)
</td>
</tr>
}
</tbody>
</table>
出租类:
namespace CarGarageSales.Models
{
[BindProperties]
public class Rental
{
[Required]
public int RentalID { get; set; }
[Required]
[Display(Name = "Price")]
[Range(100, 200000, ErrorMessage = "Price must be between 100 and 200,000 Pounds")]
public decimal Price { get; set; }
[Required]
[Display(Name = "Duration")]
[Range(1, 36,ErrorMessage = "Duration must be between 1 and 36 Months")]
public int Duration { get; set; }
[Required]
[Display(Name = "Quote")]
[Range(20, 10000, ErrorMessage = "Quote must be between 20 and 10000 Pounds")]
public decimal Quote { get; set; }
public Customer Customer { get; set; }
public virtual IList<Car> Cars { get; set; }
public virtual IList<SalesManRental> SalesManRental { get; set; }
}
}
让我们看下面的示例(这是您的实时代码)
using System;
using System.Linq;
public class Program
{
public static void Main()
{
var option = 1;
var list = new[]{ new Rental{ RentalID = 1, Quote = 1 }, new Rental{ RentalID = 2, Quote = 2 }, new Rental{ RentalID = 3, Quote = 3 }, new Rental{ RentalID = 4, Quote = 1 }, new Rental{ RentalID = 5, Quote = 3 } };
var minQuote = list.Min((p => p.Quote));
var maxQuote = list.Max((p => p.Quote));
var result = list.Where(p => (option == 1 && p.Quote == minQuote) || (option == 2 && p.Quote == maxQuote));
if(option == 0)
result = list;
foreach(var item in result)
Console.WriteLine(item.Quote);
}
public class Rental
{
public int RentalID { get; set; }
public decimal Price { get; set; }
public decimal Quote { get; set; }
}
}
注意:在 0、1、2 范围内更改option
值以测试您的案例。
只要您确定_context.Rentals
中有数据,您在else
中的最后一个示例应该可以返回 max Quote
。 我不确定你为什么使用Async Task
但你没有等待UserInput == 1
或else
中的任何内容,只有UserInput == 0
这应该工作
var Rentals = (from s in _context.Rentals select s.Quote).Max();
示例(在此处测试https://dotnetfiddle.net/2SnPcS )
using System;
using System.Collections.Generic;
using System.Linq;
public class Program {
public class Rental
{
public int RentalID { get; set; }
public decimal Price { get; set; }
public int Duration { get; set; }
public decimal Quote { get; set; }
}
public static void Main()
{
// sample data
var rentals = new List<Rental> {
new Rental { RentalID = 1, Price = 100.00m, Duration = 2, Quote = 200.00m },
new Rental { RentalID = 2, Price = 100.00m, Duration = 2, Quote = 200.00m },
new Rental { RentalID = 3, Price = 100.00m, Duration = 1, Quote = 100.00m },
new Rental { RentalID = 4, Price = 100.00m, Duration = 1, Quote = 100.00m },
new Rental { RentalID = 5, Price = 100.00m, Duration = 5, Quote = 500.00m }
};
// get min quote
var minQuote = (from s in rentals select s.Quote).Min();
// get max quote
var maxQuote = (from s in rentals select s.Quote).Max();
Console.WriteLine(string.Format("min={0} max={1}", minQuote, maxQuote));
// Outputs: min=100.00 max=500.00
}
}
我不确定您的应用程序的其余部分是什么样子或它是如何使用的,但是是的,您可以随意调用您的方法。 您只想要Quote
十进制值,还是与之关联的整个Rental
? 要根据您向我们展示的内容更改您的OnGetAsync
方法,仅获取十进制值,它看起来像这样(您几乎就在那里)。
public decimal GetQuoteAmount()
{
// this could be min
if (UserInput == 0)
{
return (from s in _context.Rentals select s.Quote).Min();
}
// this could be max
else if (UserInput == 1)
{
return (from s in _context.Rentals select s.Quote).Max();
}
else
{
// is there a third option? What do you want to happen if they do not select Min or Max?
return 0;
}
}
未经测试,但你可以这样做:
var filteredRentals = _context.Rentals.GroupBy(g => g.RentalID)
.Select(x => new Rental
{
RentalID = x.Key,
Quote = x.Max(z => z.Quote),
Duration = x.FirstOrDefault(r => r.RentalID == x.Key && r.Quote == x.Max(z => z.Quote)).Duration,
Price = x.FirstOrDefault(r => r.RentalID == x.Key && r.Quote == x.Max(z => z.Quote)).Price
}).ToList();
这个想法是您按RentalID
对其进行分组以获得 Max/Min Quote
,然后获取具有这些RentalID
和Quote
的第一条记录
如果他们有相同的报价并且您想显示所有记录而不是第一个:
var groupedRentals = _context.Rentals.GroupBy(g => g.RentalID)
.Select(x => new
{
RentalID = x.Key,
Quote = x.Max(z => z.Quote)
}).ToList();
var filteredGroupedRentals = _context.Rentals.Where(r => groupedRentals.Any(g =>
g.RentalID == r.RentalID &&
g.Quote == r.Quote))
.ToList();
正如其他人提到的,您需要使用.Select(s => s.Quote).Min()
(或.Max
)。 但是,您的select
列表选项没有任何值。 您需要指定适当的值,例如:
<option value="0">All</option>
<option value="1">Min</option>
<option value="2">Max</option>
我认为部分问题在于您仅在UserInput == 0
的情况下分配Rental
。 在其他情况下添加分配应该使您的结果在用户更改输入时更新。
此外,听起来您想获取所有具有最大(或最小) Quote
的对象的完整记录。 如果是这种情况,那么OrderBy
和GroupBy
方法应该在这里有所帮助,因为它们允许您根据数据的属性对数据进行排序,例如Quote
的值,并将具有相同值的数据分组在一起。
例如:
public async Task OnGetAsync()
{
if (UserInput == 0)
{
Rental = _context.Rentals().ToListAsync();
}
else if (UserInput == 1)
{
// Get the group of items with min quote
Rental = _context.Rentals()
.GroupBy(r => r.Quote) // Group items with the same quote (Quote becomes the Key)
.OrderBy(g => g.Key) // Order the groups by quote (smallest will be first)
.FirstOrDefault() // Choose the first group (those with min quote)
.ToListAsync(); // Select the items into a list
}
else
{
// Get the group of items with max quote
Rental = _context.Rentals()
.GroupBy(r => r.Quote) // Group items with the same quote (Quote becomes the Key)
.OrderBy(g => g.Key) // Order the groups by quote (smallest will be first)
.LastOrDefault() // Choose the last group (those with max quote)
.ToListAsync(); // Select the items into a list
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.