update sql statement with unknown name/amount of params - c#

I have a classic ASP site, that I am slowly upgrading. I would like to create a function to securely update a SQL database without specifying parameters manually. Something just a tad more dynamic.
(I do not want to use entity framework or Linq)
Here is the code so far:
string updateSql = "UPDATE sometable" + "SET test1= #testData1 " + "WHERE a = #aData1";
SqlCommand UpdateCmd = new SqlCommand(updateSql, conn);
UpdateCmd.Parameters.Add("#testData1 ", SqlDbType.NVarChar, 10, "testData1 ");
UpdateCmd.Parameters.Add("#aData1", SqlDbType.NVarChar, 20, "aData1");
UpdateCmd.Parameters["#testData1 "].Value = "21515";
UpdateCmd.Parameters["#aData1"].Value = "32t3t";
UpdateCmd.ExecuteNonQuery();
pseudo-code (what I would like to achieve)
Create an Ilist covering all variables {get; set:} [validate type/length here]
For every variable that contains a value (without validation issues) create sql update string.
Execute it.
Possible problem:
The only problem I can foresee, is that the list may have 500 variables, but each SQL update may only have only 2 or 3 columns being updated. Is this not efficient?

you need to do something like this....needs more coding obviously....
static void Main(string[] args)
{
var values = new Dictionary<string, object>( );
values.Add( "name", "timmerz" );
values.Add( "dob", DateTime.Now );
values.Add( "sex", "m" );
SqlUpdate( "sometable", values );
}
public static void SqlUpdate( string table, Dictionary<string,object> values, string where )
{
var equals = new List<string>( );
var parameters = new List<SqlParameter>( );
var i = 0;
foreach( var item in values )
{
var pn = "#sp" + i.ToString( );
equals.Add( string.Format( "{0}={1}", item.Key, pn ) );
parameters.Add( new SqlParameter( pn, item.Value ) );
i++;
}
string command = string.Format( "update {0} set {1} where {2}", table, string.Join( ", ", equals.ToArray( ) ), where );
var sqlcommand = new SqlCommand(command);
sqlcommand.Parameters.AddRange(parameters.ToArray( ) );
sqlcommand.ExecuteNonQuery( );
}

I'm not sure I fully understand what you're trying to do, but this might be close to what you're looking for. You can create an arbitrarily long list of parameters and respective values, then build the corresponding UPDATE dynamically from that list.
//set up SqlCommand
SqlCommand UpdateCmd = new SqlCommand();
UpdateCmd.Connection = conn;
//build your dictionary (probably happens elsewhere in your code)
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("col1", "col1 value");
parameters.Add("col2", 42);
parameters.Add("col3", DateTime.Now);
//build a command string and add parameter values to your SqlCommand
StringBuilder builder = new StringBuilder("UPDATE sometable SET ");
foreach(KeyValuePair<string, object> parameter in parameters) {
builder.Append(parameter.Key).Append(" = #").Append(parameter.Key).Append(",");
UpdateCmd.Parameters.AddWithValue("#" + parameter.Key, parameter.Value);
}
builder.Remove(builder.Length - 1,1);
//set the command text and execute the command
UpdateCmd.CommandText = builder.ToString();
UpdateCmd.ExecuteNonQuery();

If you are using SQL Server 2008 you have the option of passing in the parameters and their values as a table to a Stored Procedure.
Inside the Stored Procedure you can join the table to be updated with the table passed in. That would probably be more efficient than creating hundreds of sep update statements.
Here is a link that may help http://msdn.microsoft.com/en-us/library/bb675163.aspx
And here is some sample code based on the code you posted in your question
First Create a table to play with and populate it with some data
CREATE TABLE [dbo].[sometable](
[Test1] [nvarchar](100) NULL,
[a] [nvarchar](100) NULL
) ON [PRIMARY]
Insert sometable Select 'rerere', '122342'
Insert sometable Select 'sfsfw', '343'
Insert sometable Select 'sfdrgss', '434545'
Insert sometable Select 'srgegrgeg', '3939932'
Then Create the Type in SQL Server
Create TYPE dbo.ParamsType AS TABLE
( Test1 nvarchar(100), a nvarchar(100) )
Then Create the Stored Procedure that accepts the type as a parameter
CREATE PROCEDURE usp_UpdateSomeTable
#Parameters dbo.ParamsType READONLY
AS
BEGIN
SET NOCOUNT ON;
UPDATE sometable
SET sometable.Test1 = p.Test1
FROM sometable INNER JOIN #Parameters as p
ON sometable.a = p.a;
END
GO
To test from SQL Server Management Studio you can run
Declare #t as ParamsType
Insert #t Select 'newValue1', '122342'
Insert #t Select 'morenew ', '343'
Insert #t Select 'again', '434545'
Insert #t Select 'OnceMore', '3939932'
exec usp_UpdateSomeTable #Parameters=#t
To Test from C# Try
static void Main(string[] args)
{
System.Data.DataTable YourData = new DataTable("Parameters");
DataColumn column;
DataRow row;
column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "Test1";
YourData.Columns.Add(column);
column = new DataColumn();
column.DataType = System.Type.GetType("System.String");
column.ColumnName = "a";
YourData.Columns.Add(column);
row = YourData.NewRow();
row["Test1"] = "newValue1";
row["a"] = "122342";
YourData.Rows.Add(row);
row = YourData.NewRow();
row["Test1"] = "morenew";
row["a"] = "343";
YourData.Rows.Add(row);
row = YourData.NewRow();
row["Test1"] = "again";
row["a"] = "434545";
YourData.Rows.Add(row);
SqlConnectionStringBuilder connString = new SqlConnectionStringBuilder();
connString.DataSource = "127.0.0.1";
connString.InitialCatalog = "SO";
connString.IntegratedSecurity = true;
using (SqlConnection conn = new SqlConnection())
using (SqlCommand cmd = new SqlCommand())
{
cmd.CommandText = "usp_UpdateSomeTable";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
SqlParameter p = cmd.Parameters.AddWithValue("#Parameters", YourData);
p.SqlDbType = SqlDbType.Structured;
p.TypeName = "dbo.ParamsType";
cmd.Connection = conn;
conn.ConnectionString = connString.ConnectionString;
conn.Open();
cmd.ExecuteNonQuery();
}
}

Related

How to pass a list of strings a sql parameter for the stored procedure to delete?

I've got the following method that is supposed to delete the Holiday names from the database given from the List's that are passed in as arguments. The problem I am having is it isn't deleting anything from the database. Here is part of the method that I am having issues with:
private void RemoveGloOrderDays(List<SessionInfoList> sessionList, List<Holiday> selectedOrderHolidays, List<Holiday> selectedHolidays, List<string> orderDays, List<string> noOrderDays)
{
try
{
using (SqlCommand cmd = new SqlCommand())
using (SqlConnection connection = new SqlConnection(ConnectionString))
{
cmd.CommandTimeout = 600;
cmd.CommandText = "[dbo].[RemoveGlobalOrderDays]";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Connection = connection;
cmd.Parameters.Add("#SessionId", SqlDbType.Int);
cmd.Parameters.Add("#SelectedOrderHolidays", SqlDbType.NVarChar);
cmd.Parameters.Add("#SelectedHolidays", SqlDbType.NVarChar);
cmd.Parameters.Add("#OrderDays", SqlDbType.NVarChar);
cmd.Parameters.Add("#NoOrderDays", SqlDbType.NVarChar);
connection.Open();
foreach (SessionInfoList session in sessionList)
{
cmd.Parameters["#SessionId"].Value = session.SessionID;
cmd.Parameters["#SelectedOrderHolidays"].Value = DBNull.Value;
string joinedNames = string.Join(",", selectedOrderHolidays.Select(h => h.Name.Trim()));
if (!string.IsNullOrEmpty(joinedNames))
{
cmd.Parameters["#SelectedOrderHolidays"].Value = joinedNames;
}
cmd.Parameters["#SelectedHolidays"].Value = DBNull.Value;
joinedNames = string.Join(",", selectedHolidays.Select(h => h.Name.Trim()));
if (!string.IsNullOrEmpty(joinedNames))
{
cmd.Parameters["#SelectedHolidays"].Value = joinedNames;
}
Here is my stored procedure:
IF OBJECT_ID('[dbo].[RemoveGlobalOrderDays]') IS NOT NULL
DROP PROCEDURE [dbo].[RemoveGlobalOrderDays]
GO
CREATE PROCEDURE [dbo].[RemoveGlobalOrderDays]
#SessionId int,
#SelectedHolidays nvarchar(500),
#SelectedOrderHolidays nvarchar(500),
#OrderDays nvarchar(500),
#NoOrderDays nvarchar(500)
WITH ENCRYPTION
AS
BEGIN
SET NOCOUNT ON;
UPDATE [cfgSchedule]
SET
[OrderDays] = #OrderDays,
[NoOrderDays] = #NoOrderDays
WHERE [cfgSchedule].[SessionId] = #SessionID
DELETE FROM [SessionHolidayMapping]
WHERE [HolidayName] = #SelectedHolidays
AND
[SessionId] = #SessionId
DELETE FROM [SessionOrderHolidayMapping]
WHERE [SessionId] = #SessionId
AND
[HolidayName] = #SelectedOrderHolidays
END
GO
As far as I can see you are passing list of names separated by comma and you want to delete all those names. You need to use IN operator to find all holiday names that should be deleted.
Here is an example how to do it for #SelectedHolidays:
declare #SelectedHolidays nvarchar(500) = 'H1,H2,H3'
declare #SelectedHolidaysXml xml = cast(replace(N'<R><I>' + #SelectedHolidays + N'</I></R>', ',', '</I><I>') as xml)
DELETE FROM [SessionHolidayMapping]
WHERE [HolidayName] in (select x.items.value('(.)[1]', 'NVARCHAR(500)') from #SelectedHolidaysXml.nodes('/R/I') as x(items))
AND [SessionId] = #SessionId
It is ugly, but I don't know of better way to split comma separated values in sql server.
Instead of using nvarchar, you could use table valued parameters for the parameters #Selectedholidays and #selectedorderholidays and then something like
DELETE [SessionHolidayMapping] FROM [SessionHolidayMapping] A
Inner join #selectedholidays S
On A.[HolidayName] = S.Holidayname where A.[SessionId] = #SessionId.
The "HolidayName" is one column of the parameter.
I'm on my phone and cannot test it appropriately.

How do I get the primary key columns in ADO.NET?

I have a table:
CREATE TABLE [dbo].[DeliveryData](
[DeliveryId] [int] IDENTITY(1,1) NOT NULL,
...
CONSTRAINT [PK_DeliveryData] PRIMARY KEY CLUSTERED
(
[DeliveryId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
And code:
public void GetPrimaryKeyColumns(SqlConnection conn) {
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "select * from [dbo].[DeliveryData]";
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SchemaOnly);
DataTable schema = reader.GetSchemaTable();
DataColumn[] columns = schema.PrimaryKey;
...
}
cmd, reader, and schema all look good, but columns ends up a zero length array. Shouldn't it contain "DeliveryId"? How can I get the primary column "DeliveryId"?
Thanks for the help!
Blake
MSSQL doesn't return correct primary key information in all cases using GetSchemaTable. (Not too surprising. For example, almost all DB vendors support ODBC better than MS.) The following query, however, does work:
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS as tc
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE as kcu
ON kcu.CONSTRAINT_CATALOG = tc.CONSTRAINT_CATALOG
AND kcu.CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA
AND kcu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
AND kcu.TABLE_CATALOG = tc.TABLE_CATALOG
AND kcu.TABLE_SCHEMA = tc.TABLE_SCHEMA
AND kcu.TABLE_NAME = tc.TABLE_NAME
WHERE tc.CONSTRAINT_TYPE ='PRIMARY KEY'
AND tc.TABLE_SCHEMA = 'dbo'
AND tc.TABLE_NAME = 'DeliveryData'
ORDER BY ORDINAL_POSITION;
The schema table is not the DeliveryData table. You must inspect the schema table where the IsKey column is true and then grab the ColumnName field. You can then use that find the real column on a regular data table.
Update
GetSchemaTable() returns a data table of metadata information which you can see in the documentation: https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.getschematable(v=vs.110).aspx
You end up with as many rows in the returned DataTable as you would have columns in the query if you were to run the query. Here is a partial screenshot of the schema table I get from a test table in my database. Notice every column is now a row, and the IsKey field will tell you if the column is a key column:
If you want to use the PrimaryKey property on a DataTable do not use GetSchemaTable(), just use a SqlDataAdapter to fill a regular DataTable.
Update 2
use CommandBehavior.KeyInfo instead of CommandBehavior.SchemaOnly
Using SMO
using Microsoft.SqlServer.Management.Smo;
....
Server svr = new Server("Your Server Name");
Database db = svr.Databases["Your Database Name"];
Table tbl = db.Tables["DeliveryData"];
foreach (Column c in tbl.Columns)
{
bool isAKeyColumn = c.InPrimaryKey
}
This is a complete solution:
public List<string> GetPrimaryKeyColumns(DbConnection conn, string schema, string table) {
DbCommand cmd = conn.CreateCommand();
DbParameter p = cmd.CreateParameter();
p.ParameterName = "#schema";
p.Value = schema;
p.DbType = DbType.String;
p.Direction = ParameterDirection.Input;
cmd.Parameters.Add(p);
p = cmd.CreateParameter();
p.ParameterName = "#table";
p.Value = table;
p.DbType = DbType.String;
p.Direction = ParameterDirection.Input;
cmd.Parameters.Add(p);
cmd.CommandText = #"SELECT kcu.COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS as tc
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE as kcu
ON kcu.CONSTRAINT_CATALOG = tc.CONSTRAINT_CATALOG
AND kcu.CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA
AND kcu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
-- AND kcu.TABLE_CATALOG = tc.TABLE_CATALOG doesn't work on MySQL
AND kcu.TABLE_SCHEMA = tc.TABLE_SCHEMA
AND kcu.TABLE_NAME = tc.TABLE_NAME
WHERE tc.CONSTRAINT_TYPE ='PRIMARY KEY'
AND tc.TABLE_SCHEMA = #schema
AND tc.TABLE_NAME = #table
ORDER BY ORDINAL_POSITION";
DbDataReader reader = cmd.ExecuteReader(CommandBehavior.KeyInfo);
List<string> res = new List<string>();
while (reader.Read()) {
var str = reader[0];
if (str != System.DBNull.Value)
res.Add((string) str);
}
reader.Dispose();
cmd.Dispose();
return res;
}

Insert multiple rows with parameters Sql Server

I am trying to figure out if there is a way to perform a multiple values insert in Sql Server while using parameters, to be precise, having a command like this:
com = new SqlCommand("insert into myTable values (#recID,#tagID)", con);
com.Parameters.Add("#recID", SqlDbType.Int).Value = recID;
com.Parameters.Add("#tagID", SqlDbType.Int).Value = tagID;
com.ExecuteNonQuery();
Is there a way to perform a multiple values single insert with parameters taking into account that parameters may be different for each value? (Example: tagID may be always different)
I have been searching in Internet but no luck so far, thanks in advance, greetings.
You can use a table valued parameters : How to pass table value parameters to stored procedure from .net code
First, create the type, in SQL Server :
CREATE TYPE [dbo].[myTvpType] AS TABLE
(
[RecordID] int,
[TagID] int
)
And the C# code to insert your data :
internal void InsertData(SqlConnection connection, Dictionary<int, int> valuesToInsert)
{
using (DataTable myTvpTable = CreateDataTable(valuesToInsert))
using (SqlCommand cmd = connection.CreateCommand())
{
cmd.CommandText = "INSERT INTO myTable SELECT RecordID, TagID FROM #myValues";
cmd.CommandType = CommandType.Text;
SqlParameter parameter = cmd.Parameters.AddWithValue("#myValues", myTvpTable);
parameter.SqlDbType = SqlDbType.Structured;
cmd.ExecuteNonQuery();
}
}
private DataTable CreateDataTable(Dictionary<int, int> valuesToInsert)
{
// Initialize the DataTable
DataTable myTvpTable = new DataTable();
myTvpTable.Columns.Add("RecordID", typeof(int));
myTvpTable.Columns.Add("TagID", typeof(int));
// Populate DataTable with data
foreach(key in valuesToInsert.Key)
{
DataRow row = myTvpTable.NewRow();
row["RecordID"] = valuesToInsert[key];
row["TagID"] = key;
}
}
You can do this by sending your data as an xml string and convert in into table in a stored procedure in sql. For example:
suppose I am sending multiple rows to add/update in an sql table then here are the steps:
Convert your class or list of class into an xml string using following method:
public static string SerializeObjectToXmlString(object value)
{
var emptyNamepsaces = new XmlSerializerNamespaces(new[] {
XmlQualifiedName.Empty });
var serializer = new XmlSerializer(value.GetType());
var settings = new XmlWriterSettings();
settings.Indent = true;
settings.OmitXmlDeclaration = true;
using (var stream = new StringWriter())
using (var writer = XmlWriter.Create(stream, settings))
{
serializer.Serialize(writer, value, emptyNamepsaces);
return stream.ToString();
}
}
Now while sending data to the database convert your class object into xml
string (Here I am using entity framework in my code, you can do this without using it as well):
bool AddUpdateData(List<MyClass> data)
{
bool returnResult = false;
string datatXml = Helper.SerializeObjectToXmlString(data);
var sqlparam = new List<SqlParameter>()
{
new SqlParameter() { ParameterName = "dataXml", Value = datatXml}
};
var result = this.myEntity.Repository<SQL_StoredProc_ComplexType>().ExecuteStoredProc("SQL_StoredProc", sqlparam);
if (result != null && result.Count() > 0)
{
returnResult = result[0].Status == 1 ? true : false;
}
return returnResult;
}
Now your SQL Code:
3.1 Declare a table variable:
DECLARE #tableVariableName TABLE
(
ID INT, Name VARCHAR(20)
)
3.2 Insert Your xml string into Table variable
INSERT INTO #tableVariableName
SELECT
Finaldata.R.value ('(ID/text())[1]', 'INT') AS ID,
Finaldata.R.value ('(Name/text())[1]', 'VARCHAR(20)') AS Name
FROM #MyInputXmlString.nodes ('//ArrayMyClass/MyClass') AS Finaldata (R)
3.3 Finally insert this table value into your sql table
INSERT INTO MyTable (ID, Name)
SELECT ID, Name
FROM #tableVariableName
This will save your effort of hitting database again and again using a for loop.
Hope it will help you

Pass table valued parameter using ADO.NET

How to pass table valued parameter to stored procedure using ADO.NET?
Create type in SQL Server:
CREATE TYPE [dbo].[MyDataType] As Table
(
ID INT,
Name NVARCHAR(50)
)
Create Procedure:
CREATE PROCEDURE [dbo].[MyProcedure]
(
#myData As [dbo].[MyDataType] Readonly
)
AS
BEGIN
SELECT * FROM #myData
END
Create DataTable in C#:
DataTable myDataTable = new DataTable("MyDataType");
myDataTable.Columns.Add("Name", typeof(string));
myDataTable.Columns.Add("Id", typeof(Int32));
myDataTable.Rows.Add("XYZ", 1);
myDataTable.Rows.Add("ABC", 2);
Create SQL Parameter:
SqlParameter parameter = new SqlParameter();
parameter.ParameterName = "#myData";
parameter.SqlDbType = System.Data.SqlDbType.Structured;
parameter.Value = myDataTable;
command.Parameters.Add(parameter);
I tried this and received the exception:
The table type parameter '#MyDataType' must have a valid type name.
I had to set the "TypeName" property of the SqlParameter:
parameter.TypeName = "MyDataType";
This question is a duplicate of How to pass table value parameters to stored procedure from .net code. Please see that question for an example illustrating the use of either a DataTable or an IEnumerable<SqlDataRecord>.
For multilinguals, a little late to the show:
a) elsewhere on tsql
--- create a vector data type
CREATE TYPE [dbo].[ItemList] AS TABLE([Item] [varchar](255) NULL)
b)
Dim Invoices As New DataTable("dbo.ItemList") 'table name is irrelevant
Invoices.Columns.Add("Invoice", GetType(String))
...
With .SqlCommand.Parameters
.Clear()
.Add(New Data.SqlClient.SqlParameter() With {
.SqlDbType = Data.SqlDbType.Structured,
.Direction = Data.ParameterDirection.Input,
.ParameterName = "#Invoices",
.TypeName = "dbo.ItemList",
.Value = Invoices})
End With
...
' using store procedure
.CommandText = "SELECT * FROM dbo.rpt(#invoices) "
' or direct reference is a select
.CommandText = "SELECT * FROM dbo.invoicedata" +
"where ((select count(*) from #invoices) = 0 or "+
"InvoiceNumber in (select distinct * from #Invoices))
You can prefix with Exec
using( SqlConnection con = new SqlConnection( "Server=.;database=employee;user=sa;password=12345" ) )
{
SqlCommand cmd = new SqlCommand( " exec ('drop table '+#tab)" , con );
cmd.Parameters.AddWithValue( "#tab" ,"Employee" );
con.Open( );
cmd.ExecuteNonQuery( );
}

How do I translate a List<string> into a SqlParameter for a Sql In statement? [duplicate]

This question already has answers here:
Pass Array Parameter in SqlCommand
(11 answers)
Closed 6 years ago.
I seem to be confused on how to perform an In statement with a SqlParameter. So far I have the following code:
cmd.CommandText = "Select dscr from system_settings where setting in #settings";
cmd.Connection = conn;
cmd.Parameters.Add(new SqlParameter("#settings", settingList));
reader = cmd.ExecuteReader();
settingsList is a List<string>. When cmd.ExecuteReader() is called, I get an ArgumentException due to not being able to map a List<string> to "a known provider type".
How do I (safely) perform an In query with SqlCommands?
You could try something like this:
string sql = "SELECT dscr FROM system_settings WHERE setting IN ({0})";
string[] paramArray = settingList.Select((x, i) => "#settings" + i).ToArray();
cmd.CommandText = string.Format(sql, string.Join(",", paramArray));
for (int i = 0; i < settingList.Count; ++i)
{
cmd.Parameters.Add(new SqlParameter("#settings" + i, settingList[i]));
}
You appear to be trying to pass a multi valued parameter, that SQL syntax isn't going to do what you expect. You may want to pass a table value parameter.
Read this: http://www.sommarskog.se/arrays-in-sql.html#iter-list-of-strings
specifically: http://www.sommarskog.se/arrays-in-sql-2008.html#ListSqlDataRecord
private static void datatable_example() {
string [] custids = {"ALFKI", "BONAP", "CACTU", "FRANK"};
DataTable custid_list = new DataTable();
custid_list.Columns.Add("custid", typeof(String));
foreach (string custid in custids) {
DataRow dr = custid_list.NewRow();
dr["custid"] = custid;
custid_list.Rows.Add(dr);
}
using(SqlConnection cn = setup_connection()) {
using(SqlCommand cmd = cn.CreateCommand()) {
cmd.CommandText =
#"SELECT C.CustomerID, C.CompanyName
FROM Northwind.dbo.Customers C
WHERE C.CustomerID IN (SELECT id.custid FROM #custids id)";
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add("#custids", SqlDbType.Structured);
cmd.Parameters["#custids"].Direction = ParameterDirection.Input;
cmd.Parameters["#custids"].TypeName = "custid_list_tbltype";
cmd.Parameters["#custids"].Value = custid_list;
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
using (DataSet ds = new DataSet()) {
da.Fill(ds);
PrintDataSet(ds);
}
}
}
}
If you're using Sql Server 2008 or later, you can make use of table valued parameters - this allows you to pass in a table of values as a parameter. From .net you define a "structured" type SqlParameter and set the value to something that implements IEnumerable.
See the full MSDN reference with examples here: http://msdn.microsoft.com/en-us/library/bb675163.aspx
I ever use my own function to create Parameters like this:
public void SomeDataFunction() {
ArrayList params = GetParameters(someEntity);
CommandObject.Parameters.AddRange(parameters.ToArray());
}
public static ArrayList GetParameters(ISomeEntity entity) {
ArrayList result = new ArrayList {
OleDbUtility.NewDbParam("#Param1", OleDbType.Integer, , entity.Parameter1),
OleDbUtility.NewDbParam("#Param2", OleDbType.VarChar, 9, entity.Parameter2),
}
}
public static OleDbParameter NewDbParam(string parameterName, OleDbType dataType,
int size, object value) {
OleDbParameter result = new OleDbParameter(parameterName, dataType, size, string.Empty);
result.Value = value;
return result;
}
Use XML, it's plenty fast for this scenario. You would turn your list into XML and simply pass a string:
CREATE TABLE #myTempTable
( Letter VARCHAR(20) )
INSERT INTO #myTempTable (Letter) VALUES ('A'), ('B')
Declare #xml XML = '<a>A</a><a>B</a><a>C</a>'
Select * from #myTempTable
Where Letter in
(Select p.value('.', 'VARCHAR(40)') AS [Letter] from #xml.nodes('//a') as t(p))
DROP TABLE #myTempTable
I usually pass in the list as a comma separated string, and then use a table valued function to 'split' the string into a table that I can then use to join with in another query.
DECLARE #Settings TABLE (Sid INT)
INSERT INTO #Settings(Sid)
SELECT CAST(Items AS INT) FROM dbo.Split(#SettingsParameter, ',')
Unless of course you are using SQL Server 2008, then I would use the table valued parameters.

Categories