如果给出当前记录的ID,这是选择上一条和下一条记录的正确方法吗?

时间:2013-08-04 23:43:10

标签: c# sql linq entity-framework linq-to-sql

我需要运行一个LINQ查询,该查询将返回3行(当前记录,上一条记录和相对于当前记录的下一条记录.CroductID是我自动生成的标识列。

目前我正在使用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行。谢谢!

4 个答案:

答案 0 :(得分:5)

我个人会使用这种方法: 它具有在范围内缺少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);

答案 1 :(得分:3)

您的方法可以更快地重写:

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相对应的记录时,才会返回您需要的内容。

答案 2 :(得分:1)

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

答案 3 :(得分:0)

以下是我将如何解决问题 - 避免使用+ 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)