Unable to create dynamic sql query in asp.net C# - c#

I am keep getting
Conversion failed when converting the varchar value '46434,15864' to data type int.
I have this texbox which accepts numeric and commas. I need to create query with emp_num in (46434,15864) like syntax.
The query generated from codebehind is this, which runs fine manually in sql server:
SELECT * -- column names
FROM [DBO].[tablename] LPR
WHERE LPR.[EMPLOYEE_NUMBER] in (46434,15864)
code:
if (txtEmpNum.Text.Trim() != "")
{
////sb.Append(" and LPR.[EMPLOYEE_NUMBER] like '%'+ #empnumber + '%' ");
sb.Append(" and LPR.[EMPLOYEE_NUMBER] in (#empnumber) ");
cmd.Parameters.Add("#empnumber", SqlDbType.VarChar).Value = txtEmpNum.Text.Trim(); //.Replace("," , "','");
}
cmd.CommandText = sb.ToString();
DataTable dt = GetData(cmd);
gvdetails.DataSource = dt;
gvdetails.DataBind();
Table:

You will have to parametrize every value. This way you'll have dynamically created query, but NOT prone to SQL Inject
Here's code:
//where IN part of your query
string inClause = "and LPR.[EMPLOYEE_NUMBER] in ({0})";
// string arrays for values and variables of your query
string[] paramValues = txtEmpNum.Text.Trim().Split(',');
string[] paramVars = paramValues.Select((s, i) => "#empNo" + i.ToString()).ToArray();
//create query, ie. and LPR.[EMPLOYEE_NUMBER] in (#empNo0, #empNo1...)
inClause = string.Format(inClause, string.Join(", ", paramVars));
//add vars and values to command
for (int i = 0; i < paramVars.Length; i++)
{
cmd.Parameters.Add(paramVars[i], SqlDbType.Int).Value = paramValues[i];
}

You need a split function to create a list from an string. You can create that function running this script once :
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION [dbo].[fnSplitString]
(
#string NVARCHAR(MAX),
#delimiter CHAR(1)
)
RETURNS #output TABLE(splitdata NVARCHAR(MAX)
)
BEGIN
set #delimiter = coalesce(#delimiter, dbo.cSeparador());
DECLARE #start INT, #end INT
SELECT #start = 1, #end = CHARINDEX(#delimiter, #string)
WHILE #start < LEN(#string) + 1 BEGIN
IF #end = 0
SET #end = LEN(#string) + 1
INSERT INTO #output (splitdata)
VALUES(SUBSTRING(#string, #start, #end - #start))
SET #start = #end + 1
SET #end = CHARINDEX(#delimiter, #string, #start)
END
RETURN
END
Now your query will be :
SELECT *
FROM [DBO].[tablename] LPR
WHERE LPR.[EMPLOYEE_NUMBER] in (select * from fnSplitString(#empnumber, ','))
You can call it from C# exactly the same way you called your original code.

Basically the error is saying that your variable #empnumber is varchar and LPR.[EMPLOYEE_NUMBER] is integer
You can just append the value of your textbox to your query.
Edit: As others have suggested, this would be prone to SQL Injection. Marc Guillot and Nino solutions are better.

Related

Safely query SQL table with variable table name

I'm trying to make some common code for retrieving identities from tables and that involves making an unsafe query string to inject the table name.
I read everywhere that I cannot safely inject the table name. So I want to query if the table exists, then based on the result, perform a real or dummy query.
var unsafeTableQuery = "SELECT [Id] FROM [dbo].[" + tableName + "] WHERE [BulkInsertSessionID] = #bulkInsertSessionId";
var guardQuery =
"DECLARE #Exists BIT = ( SELECT CAST( COUNT(1) AS BIT ) FROM sys.tables WHERE name = #TableName AND type = 'U' );" +
"IF (#Exists = 0) SELECT TOP 0 NULL 'Id'" +
"ELSE " + unsafeTableQuery;
var cmd = new SqlCommand(guardQuery, conn, tran);
cmd.Parameters.Add(new SqlParameter("#TableName", tableName));
cmd.Parameters.Add(new SqlParameter("#bulkInsertSessionId", bulkInsertSessionId));
using (SqlDataReader reader = cmd.ExecuteReader())
{
int index = 0;
while (reader.Read())
{
int id = (int)reader[0];
entities[index++].Id = id;
}
}
Even though I have an unsafe concatenation, I'm first querying the table name against the sys.tables by a parameter. And if it doesn't exist, the IF..ELSE block will never step into the unsafe query.
For easier readability I'm expecting to run the following query:
DECLARE #Exists BIT = ( SELECT CAST( COUNT(1) AS BIT ) FROM sys.tables WHERE name = #TableName AND type = 'U' );
IF(#Exists = 0)
SELECT TOP 0 NULL 'Id'
ELSE
SELECT [Id] from <InjectedTableName> where BulkInsertSessionID = #bulkSessionId
Am I correct in my assumption that this is safe?
Suppose your users have an access to change the variable tableName. I suppose some user types it on some form. Suppose he types this:
Users]; DROP TABLE Users;--
Then your whole command will be:
DECLARE #Exists BIT = ( SELECT CAST( COUNT(1) AS BIT ) FROM sys.tables WHERE name = #TableName AND type = 'U' );
IF(#Exists = 0)
SELECT TOP 0 NULL 'Id'
ELSE
SELECT [Id] from [Users]; DROP TABLE Users;-- where BulkInsertSessionID = #bulkSessionId
This will do its IF ELSE part and then will go to next statement which is:
DROP TABLE Users;
Note that drop statement will execute in any case even if ELSE part is not executed, because you don't have BEGIN END. Note that the rest is commented out... This is most basic injection method...

How to process an integer list row by row sent to a procedure in SQL Server 2008 R2?

I have an ArrayList (in C#) that contains some int numbers (those are IDs in a table), I want to select some data for each number(s) in this ArrayList and return a table variable or a #temporary table :)
I found a solution for passing this ArrayList as an user-defined table type to my stored procedure:
CREATE TYPE [dbo].[integer_list_tbltype] AS TABLE(
[n] [int] NOT NULL,
PRIMARY KEY CLUSTERED ([n] ASC)
WITH (IGNORE_DUP_KEY = OFF)
)
GO
CREATE PROCEDURE [dbo].[Sp_apr_get_apraisors]
(#listNumbers INTEGER_LIST_TBLTYPE readonly)
AS
....
but I didn't find an efficient way to read this array as easily as in C# :(
Is there any way to write a loop for each of these numbers and save data in a temp table and finally return it to C#??
SQL is set based, so your best option is to write a single select statement that would join your input table to the tables containing the data you would like to look up. The select statement would be the result set to be sent back to your application. Then if you want to use straight ADO.Net, you can use the SqlDataReader class to read back into C#, or you could use an ORM like Linq2Sql, Entity Framework, or NHibernate. By the way, if you must do a loop in Sql, please avoid cursors. They are slow and unnecessarily complicated both to manage and to develop. Use a while loop instead.
I would suggest you change the procedure parameter to varchar(n) and then send in those values as comma-delimited string.
DECLARE #IDs VARCHAR(MAX)
SELECT #IDs = '1,2,3'
DECLARE #ID INT
WHILE LEN(#IDs) > 0
BEGIN
SELECT #ID = CONVERT(INT, LEFT(#IDs, CHARINDEX(',', #IDs + ',') -1)
-- Do something with the ID here...
SELECT #IDs = STUFF(#IDs, 1, CHARINDEX(',', #IDs + ','), '')
END
mmmmm :), after 24h (!) search aorund the www , i found my problem Answer, #Toni's answer helped me on this :) Tanx #Toni :*
1) first define stored procedure
CREATE PROCEDURE [spName]( #list_entry VARCHAR(max)=NULL)
AS
BEGIN
SELECT [Column1,column2,...]
FROM [TABLE(s)]
WHERE ( #list_entry IS NULL
OR Column1 IN (SELECT value FROM Fn_split(#list_person, ',')) )
END
2) write a function to split items (comma delimited)
CREATE FUNCTION [dbo].[fn_Split](#text varchar(8000), #delimiter varchar(20) = ' ')
RETURNS #Strings TABLE
(
position int IDENTITY PRIMARY KEY,
value varchar(8000)
)
AS
BEGIN
DECLARE #index int
SET #index = -1
WHILE (LEN(#text) > 0)
BEGIN
SET #index = CHARINDEX(#delimiter , #text)
IF (#index = 0) AND (LEN(#text) > 0)
BEGIN
INSERT INTO #Strings VALUES (#text)
BREAK
END
IF (#index > 1)
BEGIN
INSERT INTO #Strings VALUES (LEFT(#text, #index - 1))
SET #text = RIGHT(#text, (LEN(#text) - #index))
END
ELSE
SET #text = RIGHT(#text, (LEN(#text) - #index))
END
RETURN
END
GO
3) pass my array as a comma-delimited string from .NET
//defin sample array list or your data
ArrayList array = new ArrayList();
//fill array with some data
for (int i = 1000; i<1010;i++)
array.Add(i);
//define connection and command
using(SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["connString"].ConnectionString))
{
connection.Open();
SqlCommand cmd = new SqlCommand("",connection);
cmd.Parameters.AddWithValue("#list_entry", SqlDbType.varchar,8000,Get_comma_delimited_string(array));
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "yourSpName";
cmd.ExecuteNonQuery();
}
/// <summary>
/// Resturns a comma delimited string (sepearte each item in list with ',' )
/// </summary>
public string Get_comma_delimited_string(ArrayList arrayList)
{
string result = string.Empty;
foreach (object item in arrayList)
result += item.ToString() + ",";
return result.Remove(result.Length - 1);
}

Adapter Unable to fill data in dataset: Exception thrown

I have a drop down list on my web page, the selected item of which has to be passed to the Stored Procedure query in the database. However, I am getting a strange error here at adp.Fill(ds) in my bind method.
The exception always says "Incorrect syntax near the keyword 'to'.", where to is always the second word in the drop down option.
For eg: Items in dropdown- 9 to 5 (2nd word: to) , age of empires (2nd word: of)
Exceptions:
Incorrect syntax near the keyword 'to'
Incorrect syntax near the keyword 'of' etc.
Here's the method that I am using:
private void Bind(string ss)
{
SqlDataAdapter adp = new SqlDataAdapter("Retrieve", ConfigurationManager.ConnectionStrings["cn"].ConnectionString);
DataSet ds = new DataSet();
adp.SelectCommand.CommandType = CommandType.StoredProcedure;
adp.SelectCommand.Parameters.Add("#s1", SqlDbType.NVarChar, 255).Value = ss;
adp.SelectCommand.Parameters.Add("#s2", SqlDbType.NVarChar, 255).Value = DropDownList1.SelectedItem.ToString();
adp.Fill(ds);
DataList1.DataSource = ds;
DataList1.DataBind();
}
StoredProcedure
ALTER PROCEDURE [dbo].[Retrieve_SegmentedQ]
(
#s1 nvarchar(255),
#s2 nvarchar(255)
)
AS
BEGIN
DECLARE #query nvarchar(max)
SET #query = 'SELECT DISTINCT Details from tbData WHERE Name IN (' + #s1 + ') AND UnsegmentedQuery=' + #s2
exec sp_executesql #query
END
Any suggestions what's wrong here?
update the procedure like below
ALTER PROCEDURE [dbo].[Retrieve_SegmentedQ]
(
#s1 nvarchar(255),
#s2 nvarchar(255)
)
AS
BEGIN
DECLARE #query nvarchar(max)
SET #query = 'SELECT DISTINCT Details from tbData WHERE Name IN (''' + #s1 + ''') AND UnsegmentedQuery=''' + #s2 + ''''
exec sp_executesql #query
END
The bug is here:
SET #query = 'SELECT DISTINCT Details from tbData WHERE Name IN (' + #s1 + ') AND UnsegmentedQuery=' + #s2
You have stored procedure but using it as query, so making something like sql injection. as result you will have following query:
SET #query = 'SELECT DISTINCT Details from tbData WHERE Name IN (5 to 9) AND UnsegmentedQuery=age of empires
which is wrong.
make it in following way add single quotation marks to your params.
SET #query = 'SELECT DISTINCT Details from tbData WHERE Name IN (''' + #s1 + ''') AND UnsegmentedQuery=''' + #s2 + ''''
Your command text name should be same as your procedure name....and here they both are different

Multi-value date parameter in stored procedure?

I'm trying to get a stored procedure to work that accepts a multi-value parameter for dates. This isn't in SSRS but I'm trying to use the same approach as I do with it:
ALTER PROCEDURE spSelectPlacementData
(
#ClientID SMALLINT,
#SourceFileDates VARCHAR(MAX)
)
AS
BEGIN
SELECT (snip)
FROM [APS].[dbo].[Account] A
WHERE ClientID = #ClientID
AND A.[SourceFileDate] IN (SELECT * FROM dbo.Split(#SourceFileDates))
END
I use this approach with INT and VARCHAR fields on SSRS report multi-value parameters.
Here is the code I'm using to concatenate the SourceFileDates:
string sourceFileDates = "";
foreach (DateTime file in job.sourceFiles)
{
if (file == job.sourceFiles.Last())
{
sourceFileDates += "'" + file.ToString("d") + "'";
}
else
{
sourceFileDates += "'" + file.ToString("d") + "', ";
}
}
selectRunCommand = new SqlCommand("spSelectPlacementData", sqlConnection);
selectRunCommand.CommandType = CommandType.StoredProcedure;
selectRunCommand.Parameters.Add("#ClientID", SqlDbType.SmallInt);
selectRunCommand.Parameters["#ClientID"].Value = job.clientID;
selectRunCommand.Parameters.Add("#SourceFileDates", SqlDbType.VarChar);
selectRunCommand.Parameters["#SourceFileDates"].Value = sourceFileDates;
Using this dbo.Split function I grabbed online:
/****** Object: UserDefinedFunction [dbo].[Split] Script Date: 09/20/2011 11:16:13 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER FUNCTION [dbo].[Split]
/* This function is used to split up multi-value parameters */
(
#ItemList VARCHAR(MAX),
#delimiter CHAR(1)
)
RETURNS #IDTable TABLE (Item VARCHAR(MAX) collate database_default )
AS
BEGIN
DECLARE #tempItemList VARCHAR(MAX)
SET #tempItemList = #ItemList
DECLARE #i INT
DECLARE #Item VARCHAR(MAX)
SET #tempItemList = REPLACE (#tempItemList, #delimiter + ' ', #delimiter)
SET #i = CHARINDEX(#delimiter, #tempItemList)
WHILE (LEN(#tempItemList) > 0)
BEGIN
IF #i = 0
SET #Item = #tempItemList
ELSE
SET #Item = LEFT(#tempItemList, #i - 1)
INSERT INTO #IDTable(Item) VALUES(#Item)
IF #i = 0
SET #tempItemList = ''
ELSE
SET #tempItemList = RIGHT(#tempItemList, LEN(#tempItemList) - #i)
SET #i = CHARINDEX(#delimiter, #tempItemList)
END
RETURN
END
I guess I'm not entirely clear on what differs between how I'm formatting the parameter, how SSRS does so for similar parameters (this is the only one I've tried doing from code), and how the Date data type affects required formatting. I'm getting a "Conversion failed when converting date and/or time from character string." error when selecting more than one value.
Edit: As requested, example of foreach loop output:
'9/9/2011', '8/19/2011', '8/12/2011'
Why not use a Table-Valued parameter?
Create a user-defined table-type DateTimes on SQL
create type DateTimes as table
(
[Value] datetime
)
Then amend your stored procedure:
ALTER PROCEDURE spSelectPlacementData
(
#ClientID SMALLINT,
#SourceFileDates DateTimes readonly -- must be readonly
)
Now you can treat #SourceFileDates as a readonly table-variable.
When specifying your SqlCommand parameters, a Table-Valued parameter is specified as SqlDbType.Structured and passed as a DataTable or DataRowcollection. So, you can populate it like so:
var sourceFileDates = new DataTable();
sourceFileDates.Columns.Add("Value", typeof(DateTime));
foreach (DateTime file in job.sourceFiles)
{
sourceFileDates.Rows.Add(file);
}
selectRunCommand.Parameters.Add(new SqlParameter {
ParameterName = "#SourceFileDates",
Value = sourceFileDates,
SqlDbType = SqlDbType.Structured // make sure you specify structured
});
Now everything is nice and properly typed... and you don't have to do any string parsing or casting.
As a side-note, you might as well go ahead and create Strings and Integers types as well; You'll get hooked on TVPs and use them all over the place.
SSRS cheats a bit because it's controlling the inputs... it's not so concerned about SQL Injection attacks. Through a stored procedure, this would be a bit more difficult to do.
What has worked well for me when I needed to send multiple values in a single argument in 2005, I would send them as an XML string like so:
<dates>
<date>2011-01-23</date>
<date>2011-02-24</date>
</dates>
and then treat this as a table in the function:
select
x.a.value('.', 'datetime') as myDate
from
#XMLArg.nodes('/dates/date') x(a);
now you should have your data as table-valued. (syntax may be a little off, this is off the top of my head)

WHERE IN (array of IDs)

I have webservice which is passed an array of ints.
I'd like to do the select statement as follows but keep getting errors. Do I need to change the array to a string?
[WebMethod]
public MiniEvent[] getAdminEvents(int buildingID, DateTime startDate)
{
command.CommandText = #"SELECT id,
startDateTime, endDateTime From
tb_bookings WHERE buildingID IN
(#buildingIDs) AND startDateTime <=
#fromDate";
SqlParameter buildID = new SqlParameter("#buildingIDs", buildingIDs);
}
You can't (unfortunately) do that. A Sql Parameter can only be a single value, so you'd have to do:
WHERE buildingID IN (#buildingID1, #buildingID2, #buildingID3...)
Which, of course, requires you to know how many building ids there are, or to dynamically construct the query.
As a workaround*, I've done the following:
WHERE buildingID IN (#buildingID)
command.CommandText = command.CommandText.Replace(
"#buildingID",
string.Join(buildingIDs.Select(b => b.ToString()), ",")
);
which will replace the text of the statement with the numbers, ending up as something like:
WHERE buildingID IN (1,2,3,4)
Note that this is getting close to a Sql injection vulnerability, but since it's an int array is safe. Arbitrary strings are not safe, but there's no way to embed Sql statements in an integer (or datetime, boolean, etc).
First you're going to need a function and a sproc. The function will split your data and return a table:
CREATE function IntegerCommaSplit(#ListofIds nvarchar(1000))
returns #rtn table (IntegerValue int)
AS
begin
While (Charindex(',',#ListofIds)>0)
Begin
Insert Into #Rtn
Select ltrim(rtrim(Substring(#ListofIds,1,Charindex(',',#ListofIds)-1)))
Set #ListofIds = Substring(#ListofIds,Charindex(',',#ListofIds)+len(','),len(#ListofIds))
end
Insert Into #Rtn
Select ltrim(rtrim(#ListofIds))
return
end
Next you need a sproc to use that:
create procedure GetAdminEvents
#buildingids nvarchar(1000),
#startdate datetime
as
SELECT id,startDateTime, endDateTime From
tb_bookings t INNER JOIN
dbo.IntegerCommaSplit(#buildingids) i
on i.IntegerValue = t.id
WHERE startDateTime <= #fromDate
Finally, your code:
[WebMethod]
public MiniEvent[] getAdminEvents(int[] buildingIDs, DateTime startDate)
command.CommandText = #"exec GetAdminEvents";
SqlParameter buildID= new SqlParameter("#buildingIDs", buildingIDs);
That goes way beyond what your question asked but it will do what you need.
Note: should you pass in anything that's not an int, the whole database function will fail. I leave the error handling for that as an exercise for the end user.
NOTE: I am not generally for using unparameterized queries. IN THIS INSTANCE, however, given that we are dealing with an integer array, you could do such a thing and it would be more efficient. However, given that everyone seems to want to downgrade the answer because it doesn't meet their criteria of valid advice, I will submit another answer that performs horribly but would probably run in LINK2SQL.
Assuming, as your question states, that you have an array of ints, you can use the following code to return a string that would contain a comma delimited list that SQL would accept:
private string SQLArrayToInString(Array a)
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < a.GetUpperBound(0); i++)
sb.AppendFormat("{0},", a.GetValue(i));
string retVal = sb.ToString();
return retVal.Substring(0, retVal.Length - 1);
}
Then, I would recommend you skip trying to parameterize the command given that this is an array of ints and just use:
command.CommandText = #"SELECT id,
startDateTime, endDateTime From
tb_bookings WHERE buildingID IN
(" + SQLArrayToInString(buildingIDs) + ") AND startDateTime <=
#fromDate";
A superfast XML Method which requires no unsafe code or user defined functions :
You can use a stored procedure and pass the comma separated list of Building IDs :
Declare #XMLList xml
SET #XMLList=cast('<i>'+replace(#buildingIDs,',','</i><i>')+'</i>' as xml)
SELECT x.i.value('.','varchar(5)') from #XMLList.nodes('i') x(i))
All credit goes to Guru Brad Schulz's Blog
Visit T-SQL stored procedure that accepts multiple Id values for ideas on how to do this.
I use that approach and works for me.
My variable act = my list of ID's at string.
act = "1, 2, 3, 4"
command = new SqlCommand("SELECT x FROM y WHERE x.id IN (#actions)", conn);
command.Parameters.AddWithValue("#actions", act);
command.CommandText = command.CommandText.Replace("#actions", act);
[WebMethod]
public MiniEvent[] getAdminEvents(int buildingID, DateTime startDate)
...
SqlParameter buildID= new SqlParameter("#buildingIDs", buildingIDs);
Perhaps I'm being over detailed, but this method accepts a single int, not an array of ints. If you expect to pass in an array, you will need to update your method definition to have an int array. Once you get that array, you will need to convert the array to a string if you plan to use it in a SQL query.
You can use this. Execute in SQLServer to create a function on your DB (Only once):
IF EXISTS(
SELECT *
FROM sysobjects
WHERE name = 'FN_RETORNA_ID_FROM_VARCHAR_TO_TABLE_INT')
BEGIN
DROP FUNCTION FN_RETORNA_ID_FROM_VARCHAR_TO_TABLE_INT
END
GO
CREATE FUNCTION [dbo].FN_RETORNA_ID_FROM_VARCHAR_TO_TABLE_INT (#IDList VARCHAR(8000))
RETURNS
#IDListTable TABLE (ID INT)
AS
BEGIN
DECLARE
--#IDList VARCHAR(100),
#LastCommaPosition INT,
#NextCommaPosition INT,
#EndOfStringPosition INT,
#StartOfStringPosition INT,
#LengthOfString INT,
#IDString VARCHAR(100),
#IDValue INT
--SET #IDList = '11,12,113'
SET #LastCommaPosition = 0
SET #NextCommaPosition = -1
IF LTRIM(RTRIM(#IDList)) <> ''
BEGIN
WHILE(#NextCommaPosition <> 0)
BEGIN
SET #NextCommaPosition = CHARINDEX(',',#IDList,#LastCommaPosition + 1)
IF #NextCommaPosition = 0
SET #EndOfStringPosition = LEN(#IDList)
ELSE
SET #EndOfStringPosition = #NextCommaPosition - 1
SET #StartOfStringPosition = #LastCommaPosition + 1
SET #LengthOfString = (#EndOfStringPosition + 1) - #StartOfStringPosition
SET #IDString = SUBSTRING(#IDList,#StartOfStringPosition,#LengthOfString)
IF #IDString <> ''
INSERT #IDListTable VALUES(#IDString)
SET #LastCommaPosition = #NextCommaPosition
END --WHILE(#NextCommaPosition <> 0)
END --IF LTRIM(RTRIM(#IDList)) <> ''
RETURN
ErrorBlock:
RETURN
END --FUNCTION
After create the function you have to call this on your code:
command.CommandText = #"SELECT id,
startDateTime, endDateTime From
tb_bookings WHERE buildingID IN
(SELECT ID FROM FN_RETORNA_ID_FROM_VARCHAR_TO_TABLE_INT(#buildingIDs))) AND startDateTime <=
#fromDate";
command.Parameters.Add(new SqlParameter(){
DbType = DbType.String,
ParameterName = "#buildingIDs",
Value = "1,2,3,4,5" //Enter the parameters here separated with commas
});
This function get the text inner commas on "array" and make an table with this values as int, called ID. When this function is on you DB you can use in any project.
Thanks to Microsoft MSDN.
Igo S Ventura
Microsoft MVA
Sistema Ari de Sá
igo1-2#hotmail.com
P.S.: I'm from Brazil. Apologize my english... XD
Here's a Linq solution I thought up. It'll automatically insert all items in the list as parameters #item0, #item1, #item2, #item3, etc.
[WebMethod]
public MiniEvent[] getAdminEvents(Int32[] buildingIDs, DateTime startDate)
{
// Gets a list with numbers from 0 to the max index in buildingIDs,
// then transforms it into a list of strings using those numbers.
String idParamString = String.Join(", ", (Enumerable.Range(0, buildingIDs.Length).Select(i => "#item" + i)).ToArray());
command.CommandText = #"SELECT id,
startDateTime, endDateTime From
tb_bookings WHERE buildingID IN
(" + idParamString + #") AND startDateTime <=
#fromDate";
// Reproduce the same parameters in idParamString
for (Int32 i = 0; i < buildingIDs.Length; i++)
command.Parameters.Add(new SqlParameter ("#item" + i, buildingIDs[i]));
command.Parameters.Add(new SqlParameter("#fromDate", startDate);
// the rest of your code...
}

Categories

Resources