linq 在给定当前记录的ID的情况下,这是否是选择上一条和下一条记录的正确方法?

fumotvh3  于 2022-12-06  发布在  其他
关注(0)|答案(5)|浏览(190)

我需要运行一个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,
});

这应该会传回3个数据列,分别为ProductID 9、ProductID 10、ProductID 11。谢谢!

tkqqtvp1

tkqqtvp11#

就我个人而言,我会使用这种方法:它的好处是在范围内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);
a64a0gku

a64a0gku2#

您的方法可以改写得更简短一些,如下所示:

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对应的任何记录时,才会返回所需的内容。

nkkqxpd9

nkkqxpd93#

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 (...),查询执行计划器可以很好地处理它。

ds97pgxw

ds97pgxw4#

下面是我解决这个问题的方法--避免使用+1,-1。
在我的例子中,我试着显示上一个/下一个发布的博客文章。如果下一个/上一个博客文章是未发布的,+1,-1将不起作用。更不用说ID不总是连续的可能性了。
在您的情况下,您可能不想显示缺货产品。

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)

lf5gs5x2

lf5gs5x25#

以下是我的看法:

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;

相关问题