2012-06-26 30 views
1

我已经试过没有任何成功谷歌搜索,唯一的问题问不是没有找到一个解决方案:http://social.msdn.microsoft.com/Forums/pl-PL/linqtosql/thread/cee9df70-f38d-40be-ab1a-6697fac461d8EXECUTE sp_executesql的@SQL LINQ的返回void

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我收到以下消息:返回类型下列存储的过程不能被检测到。设置每个存储过程的返回类型

在此先感谢您的任何帮助。

克莱尔:-)

+0

我不知道它是否是一个错字,但是你需要使用IS来检查CustomerName变量是否为空。像** IF @CustomerName IS NOT NULL ** –

+0

我的下一个建议是避免使用C#关键字作为C#代码中的变量名称:** DateTime to,DateTime from **。我甚至不认为它的法律加它只会通过抛出编译器来引起混淆,这样你得到的错误信息可能不准确 –

+0

我将更改@CustomerName IS NOT NULL。我没有意识到来回关键字。他们指的是什么? – ClareBear

回答

1

这里的问题似乎是,如果你在一个客户名称对象传递,你的存储过程变为无效内部生成的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调用。相反,前面加上客户名称参数与%通配符,然后添加辅助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 

现在,你实际上应该得到的结果从集你的过程。这可能解决问题,返回类型无法为sproc确定。如果不是,则需要在LINQ to SQL设计器(或DBML中)中手动创建返回类型,然后将其明确设置为存储过程的返回类型。或者,您可以将数据库中的sproc拖放到新创建的类型中,以直接通过设计器自动指定返回类型。

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

+0

完全正确。此过程无效,Visual Studio无法确定返回类型。 OP应该首先运行VS外部的proc来查看错误。 – Ruslan

0

如果您正在使用DBML和MS SQL Studio中手动创建S/P。 请执行以下操作。

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

如果你在存储过程中使用动态SQL,那么当Visual Studio创建你的linq对象时,它不能告诉响应是什么类型。 (Linq只喜欢在强类型环境下工作) 您可以尝试在Visual Studio中手动更改它,这是错误消息要求您执行的操作;

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

但是,我不推荐它。首先,如果你删除并重新创建linq对象,你将不得不再次执行它,其次,它可能仍然不会给你你想要的。 我建议你回到绘图板,想出一种避免动态SQL的方法。 看看this blog entry from Scott Guthrie关于linq中的动态SQL。一旦你建立了扩展方法,这是一个更简洁的解决方案。