1

我试过谷歌搜索但没有成功,唯一的问题是没有找到解决方案: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 时,我收到以下消息:无法检测到以下存储过程的返回类型。为每个存储过程设置返回类型

提前感谢您的帮助。

克莱尔:-)

4

3 回答 3

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 永远不会像“% + @CustomerName + %”。您没有将参数传递到您的 sp_executeSQL 调用中。相反,在 CustomerName 参数前面加上 % 通配符,然后添加辅助 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 中获得一个结果集。这可能会解决无法为存储过程确定返回类型的问题。如果没有,您将需要在 LINQ to SQL 设计器(或 DBML)中手动创建返回类型,然后将其显式设置为存储过程的返回类型。或者,您可以将存储过程从数据库中拖放到新创建的类型上,以直接通过设计器自动分配返回类型。

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

于 2012-07-03T14:38:50.613 回答
0

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

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

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

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

但是,我不推荐它。首先,如果您曾经删除并重新创建 linq 对象,则必须再次执行此操作,其次,它可能仍然不会给您想要的东西。我建议您回到绘图板并想出一种避免动态 SQL 的方法。查看 Scott Guthrie 的这篇关于 linq 中的动态 SQL 的博客文章。一旦您设置了扩展方法,这是一个更简洁的解决方案。

于 2012-07-09T10:03:56.703 回答