error when i use ToList after dynamic procedure name - c#

I always use to return the number of rows ,use a foreach loop.
In a part of the project I need to get a procedure with dynamic data.
Procedure code:
ALTER procedure [dbo].[abcde]
#fldStatusIdString nvarchar(max)
as
begin
declare #Query nvarchar(max)
set #Query = '
SELECT a.fldEstateId, a.fldEstateTitle, a.fldThumbnail,a.fldPrice,fldAcceptDate
FROM (
SELECT dbo.tblImages.fldEstateId, dbo.tblImages.fldThumbnail, dbo.tblEstates.fldEstateTitle,
dbo.tblEstates.fldPrice, dbo.tblEstates.fldAcceptDate, ROW_NUMBER() OVER (PARTITION BY dbo.tblImages.fldEstateId
ORDER BY dbo.tblEstates.fldAcceptDate) AS RowNumber
FROM dbo.tblImages INNER JOIN dbo.tblEstates ON dbo.tblEstates.fldEstateId = dbo.tblImages.fldEstateId
WHERE (dbo.tblEstates.fldStatusOfAccept = 1)'
set #Query +='and (fldStatusId in('+#fldStatusIdString+'))
) AS a
WHERE a.RowNumber = 1
order by fldEstateId
'
execute sp_executesql #Query
end
When i use above procedure, can not use ToList in foreach loop.
If the normal procedure is not a problem, but if i use a above way(input data with the number of variables), I get an error.
C# Code:
List<Join_Estates_Images_Model> ListAll = new List<Join_Estates_Images_Model>();
foreach (var item in db.abcde(fldStatusIdString).ToList())
{
Join_Estates_Images_Model _entity = new Join_Estates_Images_Model();
_entity.fldEstateId = item.fldEstateId;
_entity.fldEstateTitle = item.fldEstateTitle;
_entity.fldThumbnail = item.fldThumbnail;
_entity.fldPrice = Convert.ToDecimal(item.fldPrice);
_entity.fldAcceptDate = item.fldAcceptDate;
ListAll.Add(_entity);
}
return ListAll;
Error message:
Error 14 'int' does not contain a definition for 'ToList' and no extension method 'ToList' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?)
I used 'using System.Linq'

Another way of doing it will be to pass the comma delimited list to the variable and handle it inside the procedure something like ......
Also you do not need dynamic sql here.....
ALTER procedure [dbo].[abcde]
#fldStatusIdString nvarchar(max)
as
begin
DECLARE #xml XML;
SET #xml = N'<t>' + REPLACE(#fldStatusIdString,',','</t><t>') + '</t>';
SELECT a.fldEstateId, a.fldEstateTitle, a.fldThumbnail,a.fldPrice,fldAcceptDate
FROM (
SELECT dbo.tblImages.fldEstateId
, dbo.tblImages.fldThumbnail
, dbo.tblEstates.fldEstateTitle
, dbo.tblEstates.fldPrice
, dbo.tblEstates.fldAcceptDate
, ROW_NUMBER() OVER (PARTITION BY dbo.tblImages.fldEstateId
ORDER BY dbo.tblEstates.fldAcceptDate) AS RowNumber
FROM dbo.tblImages
INNER JOIN dbo.tblEstates
ON dbo.tblEstates.fldEstateId = dbo.tblImages.fldEstateId
WHERE (dbo.tblEstates.fldStatusOfAccept = 1)
and (fldStatusId in(
SELECT r.value('.','varchar(MAX)') as item
FROM #xml.nodes('/t') as records(r)
)
)
) AS a
WHERE a.RowNumber = 1
order by fldEstateId
end

I was facing same kind of problem with entity framework. Entity framework always gives a integer resultset with dynamic query. Just follow below steps
Update your model
Drop your procedure from .edmx.
Drop result set and related function as well.
Update your procedure. Generate result set with non dynamic query.
Again add procedure in your entity.

Related

SQL query error: "Only one expression can be specified in the select list when the subquery is not introduced with EXISTS." Output parameter

I have a SQL query that is being used in a C# controller class to return search query results:
SELECT #Output = (SELECT Name, Id
FROM [dbo].[Users]
WHERE Name = 'Robert');
However, when I run this query, I get the following error:
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
I know that simply removing one of the column names will fix the issue, but I want to be able to return the Name and ID for each searched user.
Is there a way to change my query so that I can return the desired columns and still keep my #Output parameter in the query? Any recommendations would be much appreciated
One method is to concatenate them:
SELECT #Output = (SELECT Name + '|' + CONVERT(VARCHAR(255), Id)
FROM [dbo].[Users]
WHERE Name = 'Robert'
);
Another alternative is to use two variables, because you want two items:
SELECT #Name = Name, #Id = Id
FROM [dbo].[Users]
WHERE Name = 'Robert';
Given that you know that the name is 'Robert', I don't see why that is useful. You can do:
DECLARE #Name VARCHAR(255);
SET #Name = 'Robert';
SELECT #Id = Id
FROM [dbo].[Users]
WHERE Name = #Name;
Not sure if this is what you were looking for, you can declare #output as table, and insert the values when condition is true.
Declare #output table ([name] varchar(50), ID int)
insert into #output([name], id) select 'abc', 1
select * from #output
Output: This is just sample data
name ID
abc 1

Passing two strings into a stored procedure and splitting them via specific character to perform a query

I have basic procedure which basically looks like following:
create procedure zsp_selectallupceans_list
(#UPCList nvarchar(4000),
#EANList nvarchar(4000))
as
select *
from data as dd
where dd.UPC in (--myUPC list) or dd.EAN in (--myEAN list)
This is the basic idea. Now I need to somehow split this string that I passed from my C# application and it would look like following for the UPC and EAN List:
where dd.UPC in ('123','456','567') or dd.EAN in('1234','5542','412')
The UPCList parameter that is passed from C# application looks like:
'123,456,567' and eanlist: '1234,5542,412'
I have found a method which looks like this:
CREATE FUNCTION dbo.splitstring
(#stringToSplit VARCHAR(MAX))
RETURNS
#returnList TABLE ([Name] [NVARCHAR](500))
AS
BEGIN
DECLARE #name NVARCHAR(255)
DECLARE #pos INT
WHILE CHARINDEX(',', #stringToSplit) > 0
BEGIN
SELECT #pos = CHARINDEX(',', #stringToSplit)
SELECT #name = SUBSTRING(#stringToSplit, 1, #pos-1)
INSERT INTO #returnList
SELECT #name
SELECT #stringToSplit = SUBSTRING(#stringToSplit, #pos+1, LEN(#stringToSplit)-#pos)
END
INSERT INTO #returnList
SELECT #stringToSplit
RETURN
END
And the usage of this function is like following:
SELECT * FROM dbo.splitstring('91,12,65,78,56,789')
where the output is these numbers where they are split and output as a result.
Now I just need to somehow combine all this so that I can form a proper where statement based on passed parameter UPCList and EANList
Can someone help me out with this?
Updating your stored proc as below should do the trick:
create procedure zsp_selectallupceans_list
(
#UPCList nvarchar(4000),
#EANList nvarchar(4000)
)
as
select *
from data as dd
where dd.UPC in (SELECT * FROM dbo.SplitString(#UPCList)) OR
dd.EAN in (SELECT * FROM dbo.SplitString(#EANList))
You pretty much have the answer:
Compile and save the splitstring function and then your where clause will look like the following:
where dd.UPC in (Select Name From splitstring(--myUpcList)) or dd.EAN in (Select Name from splitstring(--myEanList)
Here is an XML based function for string splitting, this method is much faster than the SUBSTRING method you already found. It is also recommended to use EXISTS instead of IN for performance improvement also, see here for more information on this.
CREATE FUNCTION [dbo].[SplitString]
(
#string nvarchar(max),
#delimiter nvarchar(5)
) RETURNS #t TABLE
(
val nvarchar(500)
)
AS
BEGIN
declare #xml xml
set #xml = N'<root><r>' + replace(#string,#delimiter,'</r><r>') + '</r></root>'
insert into #t(val)
select
r.value('.','varchar(500)') as item
from #xml.nodes('//root/r') as records(r)
RETURN
END
To use:
SELECT *
FROM data t
WHERE EXISTS (SELECT 1 FROM dbo.SplitString(#UPCList,',') S1 WHERE t.UPC=S1.val)
OR EXISTS (SELECT 1 FROM dbo.SplitString(#EANList,',') S2 WHERE t.EAN=S2.val)

Cannot pass variables to a dynamic pivot query from Razor Web Pages

My Dynamic Pivot Query is as follows
var sql_ovrd = #"DECLARE #out VARCHAR(MAX)
SELECT #out = COALESCE(#out+'],[' ,'') + Hospital_Name
FROM Hospitals
SELECT #out = '['+#out+ ']'
DECLARE #sql varchar(1000)
SET #sql = '
SELECT * FROM
(
SELECT OVRCATEGORY.OVRCATEGORY AS OVRCAT, OVRCATEGORY.OVRCATEGORY AS OVRCATEGORY, Hospitals.Hospital_Name AS Hospital, OVRREPORTED.OVRCatID,
MONTH(OVRREPORTED.DATERECEIVED) AS [Month], YEAR(OVRREPORTED.DATERECEIVED) AS [YEAR]
FROM OVRREPORTED
INNER JOIN OVRCategory ON OVRReported.OVRCatID = OVRCategory.OVRCatID
INNER JOIN Hospitals ON OVRReported.Hospital_ID = Hospitals.Hospital_ID
WHERE ovrreported.cancel_id=0 AND MONTH(OVRREPORTED.DATERECEIVED) =#0 AND YEAR(OVRREPORTED.DATERECEIVED)=#1
) AS T
PIVOT (COUNT(OVRCAT) FOR Hospital IN ('+#out+')) AS P'
EXEC (#sql)"; //
var ovrd_data = db.Query(sql_ovrd,3,2015);
This keeps giving me error message that "Must declare the scalar variable "#0". Am I doing something silly?
The web grid I am trying to create works fine when I remove "AND MONTH(OVRREPORTED.DATERECEIVED) =#0 AND YEAR(OVRREPORTED.DATERECEIVED)=#1" from the Where Clause. Also when I try to execute directly on the sql studio as "AND MONTH(OVRREPORTED.DATERECEIVED) =3 AND YEAR(OVRREPORTED.DATERECEIVED)=2015" it is working perfectly.
Is it not possible to pass variables from Web Pages Razor syntax to a dynamic query?
To pass values into variable in dynamic SQL you need to use sp_executesql sys stored procedure see MSDN explication : enter link description here

must declare the scalar variable '#custid' using dbcontext.Database.SqlQuery?

I am trying to execute stored procedure from bcontext.Database.SqlQuery using EF5.
It is throwing an error must declare the scalar variable '#custid'
var results = _MiscContext.Database.SqlQuery<int>(
"exec sp_GetStaff #custid",
customerNumber).ToList<int>();
SP returns 1 if customerNumber is staff otherwise it return empty row.
ALTER PROCEDURE [dbo].[sp_GetStaff]
#custid varchar(12)
AS
BEGIN
SET NOCOUNT ON;
SELECT
1 AS [C1]
FROM [dbo].[Staff] with (nolock)
WHERE [CUSTOMER_ID] = #custid
END
How to manage this?
Since you're using named parameters, you have to specify the matching name for the parameter you're passing.
var results = _MiscContext.Database.SqlQuery<int>(
"exec sp_GetStaff #custid",
new SqlParameter("custid", customerNumber)).ToList<int>();
Try
var results = _MiscContext.Database.SqlQuery<int>(
"exec sp_GetStaff {0}",
customerNumber).ToList();

How can I return variable column lengths via LINQ to SQL

I've had a search round the internet and cannot find anything that directly matches what I'm after....
I have a stored procedure that returns a fixed set of columns (let's say ColumnA, ColumnB and ColumnC) and then additionally returns an indeterminate number / signature of additional columns (maybe ColumnD, ColumnE and ColumnF, or ColumnF, ColumnP, ColumnT and ColumnW).
The dynamic part of the query is determined by an Id param to the proc.
Unfortunately I am not in control of the schema and it has been poorly designed to have a very large number of unrelated columns added to the end (and they keep adding them), rather than having an additional table(s) to store this effectively.
As a result, I am unable to return a determinate set of columns at compile time, so LINQ to SQL cannot determine the return type of the stored procedure.
Do I have any other options, or ways I can get around this? Here's an example of what I am doing below. Can I re-write this to work with LINQ to SQL? I am writing the application with C# and SQL Server 2008 if that helps.
Thanks.
CREATE PROCEDURE [Foo].[GetBar]
(
#Id INT,
#FooVar VARCHAR(50),
#BarVar DATE
)
AS
BEGIN
CREATE TABLE #TempTbl
(
[ColumnName] VARCHAR(50)
)
INSERT #TempTbl EXEC [Foo].GetColumnNames #Id
DECLARE #ColumnNameList NVARCHAR(max)
SET #ColumnNameList = ''
SELECT #ColumnNameList = COALESCE(#ColumnNameList + '],[', '') + ColumnName FROM #TempTbl
DROP TABLE #TempTbl
SELECT #ColumnNameList = #ColumnNameList + ']'
SELECT #ColumnNameList = SUBSTRING(#ColumnNameList, 3, LEN(#ColumnNameList) )
DECLARE #FixedColumns VARCHAR(200)
DECLARE #SelectQuery NVARCHAR(max)
DECLARE #WhereQuery VARCHAR (100)
DECLARE #FullQuery NVARCHAR(max)
DECLARE #ParamaterDef nvarchar (100)
DECLARE #Foo VARCHAR(50)
DECLARE #Bar DATE
SET #FixedColumns = N'[ColumnA], [ColumnB], [ColumnC], '
SET #SelectQuery = N'SELECT ' + #FixedColumns + #ColumnNameList + N' FROM [Foo].[FooBar] '
SET #WhereQuery = N'WHERE [Foo] = #Foo AND [Bar] = #Bar'
SET #FullQuery = #SelectQuery + #WhereQuery
SET #ParamaterDef = N'#Foo VARCHAR(50), #Bar DATE'
EXECUTE sp_executesql #FullQuery, #ParamaterDef, #Foo = #FooVar, #Bar = #BarVar
END
Can you not just use a SQL Data Adapter that fills a DataSet? You could then use LINQ to DataSet and perform all of your LINQ operations:
DataTable yourDataTable = ds.Tables["TableName"];
var query =
from yourDataTable in yourDataTable.AsEnumerable()
select new
{
NewField = yourDataTable.Field<int>("ColumnName"),
NewField2 = yourDataTable.Field<string>("ColumnName2"),
};
MSDN (LINQ to DataSet)
MSDN (Single table queries using LINQ to DataSet

Categories