这是选择上一条和下一条记录的正确方法吗?给定当前记录的ID
本文关键字:一条 记录 ID 方法 选择 | 更新日期: 2023-09-27 18:26:34
我需要运行一个LINQ查询,它将返回3行(当前记录、上一条记录和相对于当前记录的下一条记录。ProductID是我自动生成的标识列。
目前,我正在使用Union LINQ声明来完成这项任务,但我不确定是否有更好或更有效的方法来完成同样的任务。
我得到的是:
var ProductID = 10;
var Results = (from p in DB.Products
where p.ProductID == ProductID - 1 //Previous record.
select new Product
{
ProductID = p.ProductID,
ProductTitle = p.ProductTitle,
Views = p.Views,
}).Union(from p in DB.Products
where p.ProductID == ProductID //Current record
select new Product
{
ProductID = p.ProductID,
ProductTitle = p.ProductTitle,
Views = p.Views,
}).Union(from p in DB.Products
where p.ProductID == ProductID + 1 //Next record.
select new Product
{
ProductID = p.ProductID,
ProductTitle = p.ProductTitle,
Views = p.Views,
});
这应该为ProductID 9、ProductID 10和ProductID 11返回3行。谢谢
就我个人而言,我会使用这种方法:它的好处是在范围内缺少Id的地方工作。一个勇敢的人认为所有的ID都已被记录并存在。
var currAndNext = Context.Set<TPoco>()
.Where<TPoco>(t=>t.id == id)
.OrderBy(t=>t.id)
.Skip(0)
.Take(2);
var prev = Context.Set<TPoco>()
.Where<TPoco>(t=>t.id == id)
.OrderByDescending(t=>t.id)
.Skip(1)
.Take(1);
您的方法可以很快重写如下:
var ProductID = 10;
var Results = (from p in DB.Products
where p.ProductID >= ProductID - 1 &&
p.ProductID <= ProductID + 1
select new Product
{
ProductID = p.ProductID,
ProductTitle = p.ProductTitle,
Views = p.Views,
});
但请注意,只有在没有从Products表中删除与指定productID对应的记录的情况下,才会返回所需的内容。
GwynBleidd提出了一个很好的解决方案,但是您也可以指定一个ID列表,在您的情况下如下:
var ids = new[] {ProductID - 1, ProcuctID, ProductID + 1};
并在where子句中使用它
var Results = from p in DB.Products
where ids.Contains(p.ProductID)
select new Product
{
ProductID = p.ProductID,
ProductTitle = p.ProductTitle,
Views = p.Views,
};
我认为这更通用,EF会将其转换为WHERE [ProductID] IN (...)
,查询执行计划器可以很好地处理它。
以下是我解决问题的方法——避免使用+1,-1。
在我的案例中,我试图显示上一篇/下一篇发布的博客文章。如果下一篇/上一篇博客文章未发布,则+1、-1将不起作用。更不用说Ids不总是连续的可能性了。
在您的情况下,您可能不想展示缺货的产品。
var products = db.Products.Where(x => x.Quantity > 0).OrderBy(x => x.ProductId).ToList();
var previous = products.LastOrDefault(x => x.ProductId < id),
var next = products.FirstOrDefault(x => x.ProductId > id)
这将返回上一个和下一个产品,其中ProductId
最接近您的起始id
。
注意:如果您的列表已按顺序排列,则不需要.OrderBy(x => x.ProductId)
。
以下是我对此的看法:
await using var context = new CsuContext(this._csuContextOptions);
var offenseLogs =
context.OffenseLogs ?? throw new Exception("SQL Connection Error");
var last = await offenseLogs.OrderByDescending(log => log.Id)
.FirstOrDefaultAsync()
.ConfigureAwait(false);
if (id == 0) id = last.Id;
var currentAndNext = offenseLogs.Where(log => log.Id >= id)
.OrderBy(log => log.Id)
.Take(2);
var current = await currentAndNext.FirstOrDefaultAsync()
.ConfigureAwait(false);
var next = await currentAndNext.Skip(1)
.FirstOrDefaultAsync()
.ConfigureAwait(false);
var previous = await offenseLogs.Where(log => log.Id <= id)
.OrderByDescending(log => log.Id)
.Take(2)
.Skip(1)
.FirstOrDefaultAsync()
.ConfigureAwait(false);
var first = await offenseLogs.OrderBy(log => log.Id)
.FirstOrDefaultAsync()
.ConfigureAwait(false);
var entry = this._mapper.Map<OffenseLog, OffenseLogDto>(current ??
throw new
Exception($"Could not find entry with id: {id}"));
entry.Next = next?.Id;
entry.Previous = previous?.Id;
entry.First = first.Id != entry.Id ? first.Id : null;
entry.Last = last.Id != entry.Id ? last.Id : null;
return entry;