【问题标题】:Model First - Full Text Search Stored Procedure - Returns Int instead of List/IENumerable模型优先 - 全文搜索存储过程 - 返回 Int 而不是 List/IENumerable
【发布时间】:2023-03-09 06:01:01
【问题描述】:

我已经寻找了几天的解决方案,但找不到。

我正在创建一个存储过程来使用全文搜索来搜索表。然后,我会将其中 15 个存储过程的结果组合成一个按其排名排序的列表。

这是存储过程的代码:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[SpAdvancedSearchICAPUsers]
    @searching nvarchar(100) = ''
AS
BEGIN
    SET NOCOUNT ON;
    Set FMTONLY OFF;

    DECLARE @SQLQuery AS NVarchar(max)

    IF @searching IS NULL OR @searching = ''
    BEGIN
        SET @SQLQuery = 'SELECT (all field names listed separated by commas) FROM Users'
    END
    ELSE
    BEGIN
        SET @SQLQuery = 'SELECT (all field names listed separated by commas), fts.Rank FROM Users as p JOIN
                    FREETEXTTABLE(Users, (fields to search for listed separated by commas), @searching) 
                    as fts on p.userID = fts.[KEY] WHERE 1=1'
    END

    EXEC @SQLQuery
END

我确实是先做模型来接触这个项目的。我通过右键单击并按下将我的存储过程添加到我的模型中:Add New > Function Import...

我设置了函数导入的名称,选择了存储过程,选择了“返回集合”到实体:(SP返回的所需数据类型,在本例中为用户)。

当我像这样使用存储过程时:

newSearch.Users = db.SpAdvancedSearchICAPUsers(search); //search is a string

newSearch.Users 是一个IENumerable<Users>。它说返回类型是存储过程的 int。我收到以下错误:

无法将类型“int”隐式转换为“System.Collections.Generic.IEnumerable”;

我还尝试在声明@SQLQuery 的下方添加一个参数定义变量,如下所示:

Declare @ParamDefinition As NVarchar(4000)

然后我设置它并尝试像这样运行它:

Set @ParamDefinition = '@searchingnvarchar(100)'

Exec sp_executesql @SQLQuery, @ParamDefinition, @searching

@searching 是传入搜索的字符串。

我什至尝试将我所有的表拖到一个 DBML 文件中,因为我以前曾以这种方式成功地使用过存储过程。当我将 SP 拖到表格中时,我收到以下消息:

UPDATE:Eddie在cmets中指定,在DBML中你拖入存储过程后,可以设置返回类型(我选择了User对象类型)。这行得通。我宁愿不这样做。我将它作为一个临时解决方案,但我有 15 个存储过程我必须这样做。

有谁知道如何使用 EDMX 文件而不是 DBML 从存储过程中获取正确的输出?当我右键单击 EDMX 并选择“映射详细信息 > 存储过程/函数”后查看属性时。 EDMX 中的返回类型没有任何内容。它没有下拉列表,什么都没有。

【问题讨论】:

  • 您是否尝试在“属性”窗口中设置存储过程的返回类型? :P 不是试图屈尊,但这就是错误所说的,你没有提到尝试它。
  • 存储过程的属性没有让我设置返回类型的地方。我不确定他们指的是实际设置的位置。我找过,到处都找不到。
  • 而且...我刚刚找到它...哇...哇。我真的到处寻找它,当你提到它时找到它。通过 make it 更改返回类型,因此我得到了一个列表,该列表有效,感谢您指出这一点并使我看起来更深入。有没有办法在不使用 LINQ 和 DBML 的情况下做到这一点?我不想对我拥有的每一个存储过程都这样做(大约有 15 个)。这是一个很好的临时解决方案,但我想在不使用 LINQ 或 DBML 文件的情况下解决问题,只使用 EF6 和我的 EDMX。
  • 请您详细说明一下?我刚刚花了一个小时试图解决这个问题。最后,我使用虚拟 SQL 生成带有正确 cmets 的 select 语句,然后将其注释掉以恢复为正确的 SQL。我确定您的解决方案可以解决我的问题,但我不明白!顺便说一句,另一个不起作用的“解决方案”是使用中间 CTE 或临时表(即使添加了 SET FMTONLY OFF)。

标签: c# sql-server asp.net-mvc-5 .net-4.5 entity-framework-6


【解决方案1】:

我不确定我是否在这里达到目的,但如果你正在做类似的事情

newSearch.Users = db.SpAdvancedSearchICAPUUsers(搜索);
并且
newSearch.Users
属于 User Entity 类型,那么可能将搜索语句写为
    Set @SQLQuery = 'SELECT p.* FROM Users as p JOIN
                     FREETEXTTABLE(Users, (fields to search for listed separated by commas), @searching) 
                     as fts on p.userID = fts.[KEY] WHERE 1=1
                     ORDER BY fts.[Rank]'

适用于它返回 用户实体 期望的字段(即:没有排名字段)这一简单事实。

为了更好地诊断是否是这种情况,问题转向:

当您发送一个空的搜索字段时,是否会出现同样的问题?

即:

newSearch.Users = db.SpAdvancedSearchICAPUsers('');

如果它适用于后一种情况,那么上述更改可能会起作用。

请告诉我。

【讨论】:

  • 我喜欢你的回答,这绝对是有道理的。我想返回实际排名的原因是因为我将组合 15 个这些存储过程并根据返回的排名对它们进行排序。我已经编辑了我的问题以包含更多信息。 newSearch.Users 是一个 IENumerable 当我尝试发送一个空字符串时,我收到以下错误:“无法将类型 'int' 隐式转换为 'System.Collections.Generic.IEnumerable'”我将尝试做第一个建议,看看它是否至少能让我得到正确的返回值。
  • 即使我删除了 fts.Rank 作为要返回的变量,它仍然给我一个整数。
  • 如果您想返回 rank 以及 User 字段,您可以保持搜索查询不变,将 rank 字段添加到非搜索查询,然后然后转到您的 EDMX 并双击模型浏览器上 Basic/Function Imports 下的 SpAdvancedSearchICAPUUsers。如果您已经将返回的集合与复杂类型相关联,那么您只需将 newSearch.Users 更改为与您的 SP 在 EDMX 模型中返回的复杂类型相同的类型(包括排名); )
  • 当您在为存储过程设置返回类型的对话框中时,如果下拉列表中没有与之关联的内容,您是否尝试单击获取列信息,然后是创建新的复杂类型(对话框底部的两个按钮)?如果你这样做了,那么你就有效地创建了一个复杂类型,你可以立即将其关联到 SP,并在以后将其用作代码中的返回类型。
  • 哦,我明白了。我不完全确定,但存储过程返回的值来自EXEC @SQLQuery 的事实可能会阻止数据库引擎找出正确的返回模式(因为@SQLQuery 是一个变量)。为什么不完全摆脱 @SQLQuery 变量并从 if 语句的每个分支返回一条 SQL 语句?
猜你喜欢
  • 1970-01-01
  • 2019-05-11
  • 2015-03-12
  • 2011-07-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多