Linq to sql LINQ到SQL——Can';t修改存储过程的返回类型

Linq to sql LINQ到SQL——Can';t修改存储过程的返回类型,linq-to-sql,stored-procedures,asp.net-3.5,Linq To Sql,Stored Procedures,Asp.net 3.5,当我将一个特定的存储过程拖到VS2008DBML设计器中时,它会显示为返回类型设置为“none”,并且它是只读的,因此我无法更改它。设计器代码将其显示为返回一个int,如果我手动更改它,它将在下一个构建中撤消 但是使用另一个(几乎相同的)存储过程,我可以很好地更改返回类型(从“自动生成类型”更改为我想要的类型) 我在两台不同的机器上遇到了这个问题。知道发生了什么吗 以下是有效的存储过程: USE [studio] GO /****** Object: StoredProcedure [dbo]

当我将一个特定的存储过程拖到VS2008DBML设计器中时,它会显示为返回类型设置为“none”,并且它是只读的,因此我无法更改它。设计器代码将其显示为返回一个int,如果我手动更改它,它将在下一个构建中撤消

但是使用另一个(几乎相同的)存储过程,我可以很好地更改返回类型(从“自动生成类型”更改为我想要的类型)

我在两台不同的机器上遇到了这个问题。知道发生了什么吗

以下是有效的存储过程:

USE [studio]
GO
/****** Object:  StoredProcedure [dbo].[GetCourseAnnouncements]    Script Date: 05/29/2009 09:44:51 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO
CREATE PROCEDURE [dbo].[GetCourseAnnouncements]
    @course int
AS
SELECT * FROM Announcements WHERE Announcements.course = @course
RETURN
而这一个没有:

USE [studio]
GO
/****** Object:  StoredProcedure [dbo].[GetCourseAssignments]    Script Date: 05/29/2009 09:45:32 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO
CREATE PROCEDURE [dbo].[GetCourseAssignments]
    @course int
AS
SELECT * FROM Assignments WHERE Assignments.course = @course ORDER BY date_due ASC
RETURN

好吧,我发现了问题。。。有点我更改了表“Assignments”的名称,忘记了更新存储过程,因此DBML设计器感到困惑。但是,即使在我更新了存储过程,从DBML设计器中删除并读取它之后,它仍然无法工作

这与此处讨论的问题几乎相同:


只有当我从数据库中删除存储过程并重新创建它、从DBML设计器中删除它、重新编译、重新启动Visual Studio并再次添加它时,它才起作用。这是我第二次在Visual Studio DBML设计器中遇到“刷新”问题…

我也多次看到这个问题,虽然我不知道是什么原因造成的,但我遇到了一种非常简单的方法来克服它。它涉及到在.dbml文件中手动编辑xml,但这是一个非常简单的编辑

右键单击解决方案资源管理器中数据上下文的
.dbml
文件(不是.layout文件,也不是designer.cs文件),然后使用XML编辑器打开它。您应该可以在
中找到存储过程块。您还应该找到要设置为
中列出的返回类型的自定义类

第一步是给自定义类一个标识符。您可以通过添加一个“Id”标记来完成此操作,如下所示,确保它在dbml文件中是唯一的:

<Type Name="MyCustomClass" Id="ID1">

第二步是告诉函数使用新ID的类型作为返回类型。通过替换
块中

<Return Type="System.Int32" />



保存文件、退出并重新生成。完成。在设计模式下重新打开.dbml文件以验证:您的过程现在将自定义类设置为返回类型。

在存储过程中使用sql用户定义类型作为参数时,也会发生这种情况


我也遇到了同样的问题,但只有当我的sp使用FTS时才会发生,我所做的是“欺骗”dbml设计器,我删除了FTS语言的内容并完美地工作,现在我可以更改返回类型。后来我转到sp并再次添加fts,效果非常好!。
希望能有所帮助。

这里找到了更好的解决方案:

我也有类似的映射问题,但我在我的案例中找到了罪魁祸首

如果您的过程或任何被调用的子过程具有临时对象,如

CREATE TABLE #result (
   ID INT,
   Message VARCHAR(50)
)
那么你就有麻烦了,即使你没有选择这些临时职位

映射程序对这些临时对象有一个一般性问题,因为可以在会话上下文中的过程之外更改类型。临时对象对于映射者来说不是类型安全的,他拒绝使用它们

用表变量替换它们,您就可以重新开始工作了

DECLARE @result AS TABLE (
   ID INT,
   Message VARCHAR(50)
)

解决这个问题的方法是:

  • 将“set fmtonly off;”添加到存储过程的开头
  • 添加该语句后,get DBML生成存储过程的代码
  • 如果存储过程的返回类型在DBML代码中仍然是“int”,请注释存储过程的整个代码,创建一个新的SELECT语句,其返回字段类型和名称与原始SELECT语句匹配,然后让DBML重新生成代码。它必须工作

    我遵循这个方法寻找更好的解决方案(与Arash的答案相同)

      阅读博客,尤其是最后一部分,因为在存储过程中添加<强> SET FMTONE > 时有一点要考虑。
    当你添加

     SET FMTONLY OFF
    
    在存储过程的开头,将其加载到DBML,
    LINQ2SQL将执行实际的存储过程

    要获取正确的返回表对象类型,
    所述存储过程在调用时必须返回某些内容(不带参数)。
    这意味着:
    1.具有所有输入参数的默认值
    2.确保SP至少返回一行数据——这就是我遇到的问题

    create table #test ( text varchar(50) );
    insert into #test (text) values ('X'); -- w/o this line, return type would be Int32
    select * from #test; -- SP returns something, proper object type would be generated
    return;
    

    我设法想出了一个更简单的方法,当时并不明显,但写下来时听起来很直截了当:

  • 从.dbml文件的设计图面中删除存储过程
  • 单击“保存所有文件”
  • 在存储过程列表上单击服务器资源管理器中的刷新
  • 将存储过程添加(拖动)到.dbml文件的设计图面上
  • 单击“全部保存”
  • 单击“构建”
  • 检查designer.cs代码文件,您将获得新版本存储过程的更新C#代码

  • 检查

    谢谢@Rubenz,我还在存储过程中使用了FTS(全文搜索),您的步骤很有效


    我对存储过程中的FTS部分进行了注释,将存储过程添加到.dbml中,然后将FTS部分取消注释回到原始状态。

    好的,我不想更改Designer.cs代码中的任何内容,我知道存在不同的问题,并且它与我的存储过程无关(反正我没有使用temp table)

    仅仅从数据库中删除sp并更新模型根本没有帮助。创建的新模型仍然存在相同的问题

    我发现,出于某种原因,在DatabaseModel->Function Imports中创建了sp的副本

    我删除了函数导入中的重复对象,并更新了模型。成功了

    问候,, Chr
    create table #test ( text varchar(50) );
    insert into #test (text) values ('X'); -- w/o this line, return type would be Int32
    select * from #test; -- SP returns something, proper object type would be generated
    return;