执行sp_executesql @SQL Linq返回VOID

时间:2012-06-26 10:21:28

标签: linq stored-procedures void

我尝试使用谷歌搜索没有任何成功,唯一的问题是没有找不到解决方案:http://social.msdn.microsoft.com/Forums/pl-PL/linqtosql/thread/cee9df70-f38d-40be-ab1a-6697fac461d8

SP

@CustomerName varchar(150) = NULL

DECLARE @SQL nvarchar(2000)

SET @SQL =  'SELECT A.[id], A.[startTime], N.firstName AS CustomerForename, N.surname AS CustomerSurname, O.Email AS OfficerEmail, L.Description AS Location, AT.description AS Type, ATC.description AS Category,AD.cancelledById, A.Deleted
FROM [Calendar].[dbo].[Appointments] AS A
INNER JOIN [Calendar].[dbo].[Name] AS N ON A.Id = N.appointmentId 
INNER JOIN [Calendar].[dbo].[Officers] AS O ON A.Officer = O.Id
INNER JOIN [Calendar].[dbo].[Locations] AS L ON A.Location = L.Id
INNER JOIN [Calendar].[dbo].[AppointmentTypes] AS AT ON A.Type = AT.Id
INNER JOIN [Calendar].[dbo].[AppointmentTypeCategories] AS ATC ON AT.category = ATC.Id
INNER JOIN [Calendar].[dbo].[AppointmentDetails] AS AD ON A.Id = AD.appointmentId
WHERE A.[id] > 1'

IF @CustomerName IS NOT NULL
SET @SQL = @SQL + ' AND (CustomerForename LIKE % + @CustomerName + % OR CustomerSurname LIKE % + @CustomerName + %)'

EXECUTE sp_executesql @SQL

LINQ

public IQueryable<Appointment> GetAppointmentsBySearchCriteria(int appointmentId, string customerName, int officer, int location, int type, DateTime to, DateTime from)
{
var data = _db.GetAppointmentsBySearchCriteria(appointmentId,customerName,officer,location,type,to,from);

foreach (var appointment in data)
{

}
}

这是我收到的错误:无法将void分配给隐含类型的局部变量

我尝试添加以下内容:

RETURN EXECUTE sp_executesql @SQL

EXECUTE sp_executesql @SQL
RETURN

当SP被拖入DBML时,我收到以下消息:无法检测到以下存储过程的返回类型。设置每个存储过程的返回类型

提前感谢您的帮助。

克莱尔: - )

3 个答案:

答案 0 :(得分:1)

这里的问题似乎是,如果传入CustomerName对象,则存储过程中生成的SQL将变为无效(并受SQL注入):

'SELECT A.[id], A.[startTime], N.firstName AS CustomerForename, N.surname AS CustomerSurname, O.Email AS OfficerEmail, L.Description AS Location, AT.description AS Type, ATC.description AS Category,AD.cancelledById, A.Deleted 
FROM [Calendar].[dbo].[Appointments] AS A 
INNER JOIN [Calendar].[dbo].[Name] AS N ON A.Id = N.appointmentId  
INNER JOIN [Calendar].[dbo].[Officers] AS O ON A.Officer = O.Id 
INNER JOIN [Calendar].[dbo].[Locations] AS L ON A.Location = L.Id 
INNER JOIN [Calendar].[dbo].[AppointmentTypes] AS AT ON A.Type = AT.Id 
INNER JOIN [Calendar].[dbo].[AppointmentTypeCategories] AS ATC ON AT.category = ATC.Id 
INNER JOIN [Calendar].[dbo].[AppointmentDetails] AS AD ON A.Id = AD.appointmentId 
WHERE A.[id] > 1
 AND (CustomerForename LIKE % + @CustomerName + % OR CustomerSurname LIKE % + @CustomerName + %)' 

CustomerForename永远不会像LIKE“%+ @CustomerName +%”。您没有将参数传递给sp_executeSQL调用。相反,在前面添加带有%通配符的CustomerName参数,然后添加secondary where子句,如下所示:

IF @CustomerName IS NOT NULL   
SET @SQL = @SQL + ' AND (CustomerForename LIKE @CustomerName OR CustomerSurname LIKE @CustomerName)'

然后按如下方式调用sp_ExecuteSql:

EXECUTE sp_executesql @SQL, N'@CustomerName NVarChar(150)', @CustomerName

现在,您应该从proc获得结果集。这可以解决无法为sproc确定返回类型的问题。如果没有,则需要在LINQ to SQL设计器(或DBML)中手动创建返回类型,然后将其显式设置为存储过程的返回类型。或者,您可以从数据库中拖动sproc并将其放在新创建的类型上,以直接通过设计器自动分配返回类型。

您也可以尝试使用SqlMetal生成dbml,因为它可以更好地检测存储的proc返回类型而不是设计器。

答案 1 :(得分:0)

如果您使用DBML并在MS SQL Studio中手动创建s / p。 请执行以下操作。

  1. 从数据库中删除存储过程,重新创建它。
  2. 使用MS SQL Studio中新创建的存储过程运行测试,确保返回数据。
  3. 从DBML Designer中删除s / p,保存,重新编译,重新启动Visual Studio并重新添加。
  4. 如果您遇到问题,请将屏幕截图和您的dbml文件发布以查看。

答案 2 :(得分:0)

如果在存储过程中使用动态SQL,那么当visual studio创建linq对象时,它无法确定响应的类型。 (Linq只喜欢在强类型的环境中工作) 您可以尝试在visual studio中手动更改它,这是错误消息告诉您要做的事情;

  • 在visual studio中,将DBML文件打开到设计器视图中并正常添加SP。
  • 确定错误消息,然后从设计器的列表中选择SP的名称。右键单击并点击属性。
  • 隐藏在属性对话框中,您将找到可以手动设置的“返回类型”。试验一下,看看你能从中得到什么。

但是,我不推荐它。首先,如果您删除并重新创建linq对象,则必须再次执行此操作,其次它可能仍然无法提供您想要的内容。 我建议你回到绘图板,想出一种避免动态SQL的方法。 查看关于linq中动态SQL的this blog entry from Scott Guthrie。一旦你设置了扩展方法,它就是一个更简洁的解决方案。