linq2db是否可以创建按特定列具有ORDER BY但在SELECT中不包含该列的查询?

时间:2019-01-18 17:55:56

标签: c# linq asp.net-core .net-core linq2db

我正在使用linq2db作为带有Oracle数据库的项目(ASP.NET Core 2.2)的ORM。我想从按特定列排序的数据库中获取产品列表,但是不需要在前端客户端上显示该列。

我正在寻找的SQL查询应该是这样的:

SELECT Id, Name 
FROM Products
ORDER BY InternalOrder

因此,当我在C#代码中使用linq2db时,如下所示:

using (var db = new ProductsDao())
{
    return db.Products.Select(p => new Product
        {
             Id = p.Id,
             MarketName = p.MarketName
        })
        .OrderBy(p => p.InternalOrder)
        .ToArray();
}

然后linq2db将其转换为以下SQL查询:

SELECT
    t1.Id,
    t1.Name
FROM
    Products t1
ORDER BY
    NULL

请注意,“ ORDER BY NULL”实际上不会进行任何排序。

但是,如果我在Select()中添加InternalOrder像这样:

using (var db = new ProductsDao())
{
    return db.Products.Select(p => new Product
        {
             Id = p.Id,
             MarketName = p.MarketName,
             InternalOrder = p.InternalOrder  // this is added
        })
        .OrderBy(p => p.InternalOrder)
        .ToArray();
}

然后我在生成的SQL查询中获得正确的ORDER BY子句:

SELECT
    t1.Id,
    t1.Name,
    t1.InternalOrder
FROM
    Products t1
ORDER BY
    t1.InternalOrder

但是,在这种情况下,我不得不在SELECT语句中包括InternalOrder列,这是我要避免的事情,因为我在结果中不需要该字段。

请注意,在实际的应用程序中,我可能有很大的表,并且有多个列要排序,但不想包含在结果中。不从数据库获取这些列的值应该为我节省一些性能成本。

为确保代码完整性,这是我在上面的示例中使用的与linq2db相关的类:

[Table(Name = "Products")]
public class Product
{
    [Column(Name = "Id")] 
    public decimal Id { get; set; }

    [Column(Name = "Name")] 
    public string Name { get; set; }

    [Column(Name = "InternalOrder", CanBeNull = false)] 
    public int InternalOrder { get; set; }
}       

public class LiveEventServiceDao : LinqToDB.Data.DataConnection
{
    public LiveEventServiceDao() : base("MyOracleDb")
    {
    } 
    public ITable<Product> Products => GetTable<Product>();
}

是否可以使用linq2db完成此操作?

1 个答案:

答案 0 :(得分:2)

Try following :

return db.Products.Select(p => new {Order = p.InternalOrder, Prod = p})
         .OrderBy(p => p.Order)        
         .Select(p => new Product {
        {
             Id = p.Prod.Id,
             MarketName = p.Prod.MarketName
        })

        .ToArray();