Working with parameterized stored procedure in ASP.NET - asp.net

So, my SQL Server admin has given me access to a stored procedure with 5 parameters that returns 15 columns of data.
However, if I want to filter on the columns that are not parametrized, I have just a few options. Creating a DataSet does not help, since the query to the database can only be the stored proc and it's parameters, not Select statements.
I can create an XML file and query that using Linq-to-XML
I can create some temporary tables in another database and query those
What am I missing?

some ideas...
1) Can you ask your dba for a new stored procedure that filters (using additional parameters) on columns you need to filter on?
2) Can you write your own stored procedures? If so, you could, for example declare a table variable, insert into it using an exec on the stored procedure your dba wrote, and then select from it using any filters you like.
3) re: your two options -- those will work -- you can pull all of the data into a datatable in asp.net, or an xml file, but that's moving and exposing data you know at design time you won't need, so not an ideal solution.
4) Can you directly query the table(s) yourself?
EDIT
You can bring (all) of the data into a datatable (asp.net), and then filter it there. For example (VB):
Dim myFilter as String
myFilter = "SomeField = SomeValue"
Dim myRows() as datarow
myRows = myDataSet.Tables(i).Select(myFilter)
For each myRow as datarow in myRows
myNewDataTable.ImportRow(myRow)
Next
It's not ideal, but considering the limitations...

Creating a DataSet does not help, since the query to the database can
only be the stored proc and it's parameters, not Select statements.
A DataSet can be filled using a stored procedure. When you filled up your DataSet then you filter the records using whatever data access technology you know/like.
marc_s is right, get a new DBA. If he doesn't want to create a stored procedure or add parameters to the existing procedure then he probably won't mind your application getting 1,700 records every time you call that stored procedure when all you really need is a subset of those records.

You can bring the data back into a DataSet and then use a DataView object to apply a filter. In short, this will call the stored procedure, gather all of the rows into the DataSet, and then the DataView will let you enumerate the data skipping over rows that don't match the filter.
Here's an example in C#: C# DataView Usage

If the number of records you get back is not huge, you could do this:
Create a POCO class to represent the data record coming back from the stored proc:
public class MyRecord
{
Field1Name { get; set;}
...
Field10Name { get; set;}
}
Populate a List<MyRecord> with the results coming back from your stored proc:
List<MyRecord> mylist = new List<MyRecord>();
foreach(record in collectionOfRecordsFromStoredProc)
{
mylist.Add(new MyRecord {
Field1Name = "", /* retrieve your value from record here */
...
Field10Name = "" /* retrieve your value from record here */
});
}
Then you can query those results using the standard Linq to Objects:
List<MyRecord> filteredRecords = mylist.Where(x => x.Field10Name.Contains("Smith")).ToList();
This essentially will do everything in memory without an intermediaray place to persist the data. But this will not scale well if you are expecting to receive very large numbers or records back from this stored proc.
NOTE: code above is untested so will probably need tweaking

Related

Removing a sort from dataview

I have a dataview which binds to a PagedDataSource object. The data is pulled into the dataview from the db using a stored procedure and the returned data is sorted according to a date field. The stored proc is used in several places in the application and so I cant make any big change in this instance. I just need to disable the sort order which is returned by the stored proc (Without making any change to the stored proc) and apply a new sort.
objPagedDs = New PagedDataSource()
dvFeedback = objCompany.PublishedMonitoringCards.DefaultView
dvFeedback.RowFilter = "EligibleForPrinting = 1"
dvFeedback.Sort = "IncludeInRepReport DESC, Work_dt DESC"
Please find the code above.
I have 0,1,and null values in the database. It sorts Includeinreport in descending order. That means it sorts in the order of 1,0, and null. Apparently I want the null to be 0 when it returns from the database to make the sort working the way I want. Used ISNULL to do it. Doesnt relate to question but this what I did. The above code snippet is fine.

Getting Table Field Names as a String

I'm trying to get the list of field names for a given table, to turn them into a string which I can to post back as a variable to another function.
I've Googled loads of stuff regarding GetSchemaTable but all I seem to be able to output are field parameters, but not the actual value of these parameters (ie ColumnName, which is the one I actually want!)
Found this page; What is the SQL command to return the field names of a table?
But all the queries on there give me an error "You do not have access to Table 'Columns'"
I feel sure this is pretty simple, can someone give me a little function that will simply give me
fieldNames = "fieldName1, fieldName2, etc"
I am using a MySQL server and ODBC connections ASP.NET using VB.
I don't know if this will work, but give it a try.
Instantiate a OdbcCommand with something like select * from yourtable limit 0;
Load a DataTable with the datareader returned from cmd.ExecuteReader.
DataTable dt as new DataTable()
dt.Load(cmd.ExecuteReader())
Now iterate through the columns of dt to find out what the column names are.
This is just and idea. Don't know if it will work or not.

Using a SQL Function to Format Account info?

I have a SQL function that I am calling in my VB.Net code within a display function. The SQL function will format my account data to include the following results form a Table.
The table data: "001000011121" (this is the type of structure the data has before formated)
So the data table data and vb Properties would be called Myaccount, HerAccount, ThisAccount.
Once the data is pulled and then formatted in the VB.net code it will result into a GridDisplay as as: "001.00.001.1121"
The way I have my Public Function in my code is:
Public Funcion GetDisplay(_
ByVal dbBass as DataProvider_
,ByVal pps AS TMGDatarequestParms_
,By filter As IFilter_
) As Ilist
Dim strobe As String = CType(parms.OptionalParameters, DataProvider).Database
Dim sql As BiGSqlBuilder(TABLE)
sql.Select = String.Format("ID, [{0}].dbo.GLForamtAcct(Myaccount) AS [Myaccount], [{0}].dbo.GLFormatAccount(HerAccount) AS [HerAccount], [{0}].dbo.GLFormatAccount(ThisAccount) AS [ThisAccount]", strobe)
I left out some of the return code since not necessary. The only thing I'm concerned is how to format the SQL within the VB.net Code above. I hope this makes sense I'm new to this whole abstraction stuff. Any help would be Highly appreciated cause I'm pretty sure how I have it above does not work.
Suggest implementing your display code in your higher tiers, rather than burdening your database with this business logic.
It sounds like you're string to use String.Format() to insert the table name in your string. This syntax of database.schema.object is really only needed if performing cross database calls.
If you really want to use your SQL UDF to perform your formatting, suggest using/formulating a SELECT statement like:
SELECT ID,
dbo.GLFormatAccount(Acct1) AS Acct1,
dbo.GLFormatAccount(Acct2) AS Acct2,
dbo.GLFormatAccount(Acct3) AS Acct3
FROM MyTable

How to store Multiple radio button and check box values in sqlserver database using Asp.net?

I am making database using sqlserver2008. Which data type I should choose? In php I use ENUM and in value field I put like that 'Male','Female'. what is the way in sqlserver to create radio button and check box field? And how to insert these in sqldatabase?
I have two gender radio button with different ids so I apply check before insertion i.e.
connection.open();
string gen = "";
if(rdm.Checked == true)
{
string gen ="Male";
}
else if (rdf.Checked == true)
{
string gen = "Female";
}
and in insert value field I just put +gen+ but I receive error: Error 1 A local variable named 'gen' cannot be declared in this scope because it would give a different meaning to 'gen', which is already used in a 'parent or current' scope to denote something else
I usually store dotnet Enums as integers (smallint) in SQL server, sometimes when the database is queried directly by users I use varchar values for readability. Both can easily be converted back to Enums.
I will commonly create a code table in the database to represent my .net enums. Then the associated field in the main data table is just an int with a FK constraint to the code table.
This allows for compact storage and transmission of the data, ensures that no out of range values are entered into the database, and if anyone needs to query the db directly they can join to the code tables to find out what the integers mean.

Mass sending data to stored procedure

I'm using Microsoft .NET Framework 3.5 to create a web service with VB.NET. I'm using a Stored Procedure in SQL Server 2008 so that SQL can insert all the data that I'm passing.
The problem is that in one of the servicse I need to pass around 10,000 records and it's not very efficient to run the stored procedure 10,000 times.
I read that there is a way in which you can pass an XML file with all data to the Stored Procedure but I'm not sure if that's the most efficient way. Also I couldn't make the code work, I don't know if I have to pass the XML as a String.
I'm asking for help with a method in which I can pass a lots of records to the stored procedure once and then the same instance of the Stored procedure can process all the records in a loop
Thank you all in advance.
There is SqlBulkCopy in .NET, but I expect you'll want to look at a table-valued parameter.
You can pass a text batch of statements to the database. It can be quite efficient.
Instead of creating a SqlCommand of CommandType.StoredProcedure and taking a single stored procedure name and set of parameters – which, as you suspect, will perform poorly if you round-trip to the database for each record – you can instead create a SqlCommand of CommandType.Text, and then construct a text batch containing multiple SQL statements (which would be invocations of your stored procedure.) Separate each statement with a semi-colon.
Another advantage of a text batch is that your stored procedure can be kept simple and just process a single record at a time.
But, be careful: You need to ensure your parameters are properly quoted / escaped, because creating a plain text batch instead of using CommandType.StoredProcedure (with parameters) opens you up to SQL-injection type vulnerabilities.
The method I use is to pass the data in a CDATA block (pipe delimited in my case) to the web service, which then:
Saves the CDATA block to a temp file on the web server
Then uses the command line utility bcp.exe to bulk load the data into a staging table
Then calls the stored procedure which is set up to process all the records in the staging table
much faster and less strain on the database than calling the proc for each record.
Edit: Now that I've read about SqlBulkCopy, I would do this instead:
Write the CDATA block data into a DataTable
Use SqlBulkCopy to put the data into a staging table :-)
Then calls the stored procedure which is set up to process all the records in the staging table
http://msdn.microsoft.com/en-us/library/ms186918.aspx
This may also help: http://sqlxml.org/faqs.aspx?faq=61
Where I've done this before with SQL Server 2000, I've used OPENXML (as #EJB suggested) by constructing an XML string in my code, passing it into a stored proc in a text parameter, using OPENXML to parse the XML into a relational structure and going on from there e.g.
VB
Dim xmlStringBuilder As System.Text.StringBuilder
xmlStringBuilder = New System.Text.StringBuilder
xmlStringBuilder.Append("<objects>"
For Each object In Collection
'I'm not suggesting this is the best way to build XML, it is however reliable!
xmlStringBuilder.Append("<object id='" & object.id.ToString & "'></object>"
Next
xmlStringBuilder.Append("</objects>"
Dim xmlStoredProcCommand As SqlCommand
Dim xmlParameter As SqlParameter
xmlStoredProcCommand = New SqlCommand(connection)
xmlStoredProcCommand.CommandType = CommandType.StoredProcedure
xmlStoredProcCommand.CommandText = "xmlStoredProc"
xmlParameter = New SqlParameter("#xmlParameter",SqlDbType.NText)
xmlParameter.Value = xmlStringBuilder.ToString
xmlStoredProcCommand.Parameters.Add(xmlParameter)
xmlStoredProcCommand.ExecuteNonQuery
SQL
CREATE PROCEDURE xmlStoredProc
#xmlParameter NTEXT
AS
BEGIN
DECLARE #xmldochandle INT
DECLARE #objects TABLE (objectID INT)
EXEC sp_xml_preparedocument #xmldochandle OUTPUT, #xmlParameter
INSERT INTO #objects (objectId)
SELECT objectId
FROM OPENXML(#xmldochandle, 'objects/object')
WITH (objectId INT)
EXEC sp_xml_removedocument #xmldochandle
END
and from there you can do your stuff with the contents of the #objects table variable.

Resources