![](/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.