【问题标题】:Order by not-selected column按未选择的列排序
【发布时间】:2020-02-27 14:42:32
【问题描述】:

我正在尝试使用 SQL 运算符 CONTAINSTABLE 来获取搜索结果列表,如下所示:

SELECT c.*, ccontains.[RANK]
FROM Customers c
INNER JOIN CONTAINSTABLE(Customers, LastName, @searchTerm) ccontains ON c.Id = ccontains.[KEY]

并从 EF Core 2.1 调用此函数:

var query = DbContext.Customers.FromSql("SELECT * FROM udfSearchCustomers(@searchTerm)",
    new SqlParameter(@searchTerm, mySearchTerm));
query = query.Include(c => c.Addresses).Take(maxResults);

我想按RANK 降序排列我的搜索结果,以便在顶部获得最相关的结果。不允许将ORDER BY ccontains.[RANK] 添加到我的函数中,因为我的SELECT * FROM udfSearchCustomers(...) 将被EF Core 包装:内部查询中不允许ORDER BY。无法添加query.OrderBy(c => c.Rank),因为RANK 不在Customer 实体上。

我已经尝试使用System.Linq.Dynamic 以及其他反射解决方案来做到这一点:

query = query.OrderBy("Rank");

但我有一个例外:

“排名”不是“客户”类型的成员

这是真的。有没有办法对不在实体上的列进行排序,或者我需要创建一个MyCustomerSearchQuery 查询对象并使用 AutoMapper 将它们转换为Customer?我宁愿不这样做,因为Customer 有很多属性,要让它们保持同步会很麻烦。

提前致谢!

【问题讨论】:

    标签: c# linq entity-framework-core contains containstable


    【解决方案1】:

    您可以创建带有两个参数的查询存储过程:@searchKey、@orderByColumn。

          CREATE PROCEDURE [dbo].[UdfSearchCustomers]
                     @searchTerm varchar(50),
                     @orderByColumn varchar(50)
    
              AS
              BEGIN
              DECLARE @sql NVARCHAR(MAX);
              SET @sql =' SELECT c.*, ccontains.[RANK]
                      FROM Customers c
                      INNER JOIN CONTAINSTABLE(Customers, LastName, ''@searchTerm'') ccontains 
                      ON c.Id = ccontains.[KEY]
                      ORDER BY @orderByColumn'
    
                SET @sql = REPLACE(@sql, '@orderByColumn', @orderByColumn)
                SET @sql = REPLACE(@sql, '@searchTerm', @searchTerm)
                exec sp_executesql @sql
                END
    
        GO
    

    然后就可以查询同样的存储过程了:

    var query = DbContext.Customers.FromSql("exec UdfSearchCustomers @p0, @p1", mySearchTerm, "Rank");
    

    如果您想将连接添加到地址表,那么您可以将连接添加到存储过程。这可能会给您想要的结果。

    【讨论】:

      【解决方案2】:

      你可以试试

       query = query.OrderBy(x => x.Rank);
      

       query = query.OrderBy(x => x["Rank"]);
      

      【讨论】:

      • 唉,Rank 不是 Customer 上的属性,因此无法编译
      • 你能创建 1 个新的模态吗?此模式继承客户类并创建 Rank 属性。设置此模态返回类型
      • 也试过了 :) EF Core 拒绝了这个新类,说查询对象和实体可能不在同一个继承树中。
      • 调用存储过程并返回结果的最佳方式
      猜你喜欢
      • 2012-11-14
      • 1970-01-01
      • 1970-01-01
      • 2011-07-01
      • 1970-01-01
      • 2015-02-17
      • 1970-01-01
      • 2018-07-03
      • 1970-01-01
      相关资源
      最近更新 更多