Using ADO versus stored procedure for Create and Update - stored-procedures

Using ADO versus stored procedure for Create and Update
I am using Classic ASP, SQL server 2008 R2. I have been using ADO like this to do create and updates:
sSQL = "select <column list> from <table>"
set rsMyTable = Server.CreateObject ("ADODB.Recordset")
rsMyTable.cursorType = 2
sMyTable.LockType = 3
rsMyTable.open sqlstr, objMyConnection
rsMyTable.addnew
rsMyTable("Mycol1") = myValue1
rsMyTable("Mycol2") = myValue2
rsMyTable.update
rsMyTable.close
set rsMyTable = nothing
I have several tables that need to be updated and each update updates different sets of columns. Is it a bad practice to use ADO like this? Instead of using ADO, should I create stored procedures for each update and pass parameters to the stored procedure using ADO like this:
sqlstr = "myUpdateProcedure"
set objCmd = Server.CreateObject("ADODB.Command")
set objParam = Server.CreateObject("ADODB.Parameter")
set objCmd.ActiveConnection = objConnection
objCmd.commandText = sqlstr
objCmd.CommandType = 4 ''stored proc.
set objParam = objCmd.CreateParameter("param1", 19, 1, , value1)
objCmd.Parameters.Append objParam
set objParam = objCmd.CreateParameter("param2", 200, 1, <maxlength>, value2)
objCmd.Parameters.Append objParam
....
set rsTemp = Server.CreateObject("ADODB.Recordset")
rsTemp.CursorLocation = adUseClient
rsTemp.CursorType = adOpenKeyset
set rsTemp = objCmd.Execute()
....
''cleanup.
set objParam = Nothing
set objCmd = Nothing
Set rsTemp = Nothing
I appreciate any advice.
Thanks.

Create a stored procedure to perform all the updates. You can then use transactions to ensure that all updates are performed or rolled back. In other words move the logic you currently have in VBScript to T-SQL.
Using ADO in this way is arcahic at best and performs poorly.
If you have a lot of parameters to pass or multiple rows to update consider using XML as transport into the stored procedure.

Related

How to insert into a table field with value from a display method dependent of string

as you might know, this is a nice way to dynamically set values to fields.
myTable.(fieldName2Id(myTable.TableId, fieldNameStr)) = "This value";
myTable.insert();
What I am wondering about is if there is any way to do it in a similar fashion with display methods, just dynamically get the values from them?
If i have the Display method name (i.e. itemName()) how can I do this...?
something like this to demonstrate how i think:
methodNameStr = "ItemName";
myTable.myField = mytable.(methodName2Id(myTable.TableId, methodNameStr));
myTable.insert();
Use DictTable.callObject(medhodName, buffer).
Common myTable;
DictTable dt;
//<SampleOnly>
str methodNameStr = "itemDescriptionOrName";
InventTable tmpTab;
select firstOnly tmpTab;
myTable = tmpTab;
//</SampleOnly>
dt = new DictTable(myTable.TableId);
dt.callObject(methodNameStr, myTable);
info(strFmt("%1", dt.callObject(methodNameStr, myTable)));

How can I check results for select statement in MVC?

Hi this is the SP I have :
USE [Tracker_Entities]
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[uspHub]
#id int
AS
BEGIN
SELECT DISTINCT table1.UID, table1.url, Scope.ID
FROM table1 INNER JOIN
Scope ON table1.UID = Scope.newBrand
WHERE (table1.value = 0) AND (Scope.ID = #id)
ORDER BY table1.url
END
GO
When i run this SP in sql server by passing ID as parameter i am getting expected result. Now I need to check this SP in mvc. This is the way I am calling this SP in my MVC :
using (var ctx = new database_Entities())
{
int ID = 122;
ctx.uspHub(ID);
ctx.SaveChanges();
}
But when I put breakpoint in using statement and check for results, it is not displaying any results. I am struggling here for long time and i am not getting proper solution for this. So what are the steps in MVC to check results for SP which has select statements??
Update :
I got solution for this after using tolist. Now i am getting three results in list and i need to grab one result that is URL and pass it as input parameter.
My code :
int ID = 413;
var x = ctx.uspdHub(ID).ToList();
Here x has 3 results. I need to take one result from it.I tried doing x. but it doesn't show results after i type dot. How can i achieve this??
You have to Get the result into proper model/object.
List<YourEntity> model;
using (var ctx = new database_Entities())
{
int ID = 122;
model = ctx.uspHub(ID).toList();
//ctx.SaveChanges(); - no need to call SaveChanges
// - as you are not updating anything
}
Go through this article if you need more info. Call Stored Procedure From Entity Framework (The code above will work anyways...)
use...
using (var ctx = new database_Entities())
{
int ID = 122;
var result = ctx.uspHub(ID);
}
and add a break after the result to see whats in the result variable. Obviously, the sope of result will need to be moved, but I'm only showing here how you can see the data returned.
Try to use something like this:
using (var dataContext= new database_Entities())
{
int ID = 122;
SomeEntity[] result = dataContext.Database.SqlQuery<SomeEntity>("[dbo].[uspHub] #id",new SqlParameter("#id", ID)).ToArray();
}
It is good for me. I have used ORM EntityFramework to connect with DB.

Passing query parameters in Dapper using OleDb

This query produces an error No value given for one or more required parameters:
using (var conn = new OleDbConnection("Provider=..."))
{
conn.Open();
var result = conn.Query(
"select code, name from mytable where id = ? order by name",
new { id = 1 });
}
If I change the query string to: ... where id = #id ..., I will get an error: Must declare the scalar variable "#id".
How do I construct the query string and how do I pass the parameter?
The following should work:
var result = conn.Query(
"select code, name from mytable where id = ?id? order by name",
new { id = 1 });
Important: see newer answer
In the current build, the answer to that would be "no", for two reasons:
the code attempts to filter unused parameters - and is currently removing all of them because it can't find anything like #id, :id or ?id in the sql
the code for adding values from types uses an arbitrary (well, ok: alphabetical) order for the parameters (because reflection does not make any guarantees about the order of members), making positional anonymous arguments unstable
The good news is that both of these are fixable
we can make the filtering behaviour conditional
we can detect the category of types that has a constructor that matches all the property names, and use the constructor argument positions to determine the synthetic order of the properties - anonymous types fall into this category
Making those changes to my local clone, the following now passes:
// see https://stackoverflow.com/q/18847510/23354
public void TestOleDbParameters()
{
using (var conn = new System.Data.OleDb.OleDbConnection(
Program.OleDbConnectionString))
{
var row = conn.Query("select Id = ?, Age = ?", new DynamicParameters(
new { foo = 12, bar = 23 } // these names DO NOT MATTER!!!
) { RemoveUnused = false } ).Single();
int age = row.Age;
int id = row.Id;
age.IsEqualTo(23);
id.IsEqualTo(12);
}
}
Note that I'm currently using DynamicParameters here to avoid adding even more overloads to Query / Query<T> - because this would need to be added to a considerable number of methods. Adding it to DynamicParameters solves it in one place.
I'm open to feedback before I push this - does that look usable to you?
Edit: with the addition of a funky smellsLikeOleDb (no, not a joke), we can now do this even more directly:
// see https://stackoverflow.com/q/18847510/23354
public void TestOleDbParameters()
{
using (var conn = new System.Data.OleDb.OleDbConnection(
Program.OleDbConnectionString))
{
var row = conn.Query("select Id = ?, Age = ?",
new { foo = 12, bar = 23 } // these names DO NOT MATTER!!!
).Single();
int age = row.Age;
int id = row.Id;
age.IsEqualTo(23);
id.IsEqualTo(12);
}
}
I've trialing use of Dapper within my software product which is using odbc connections (at the moment). However one day I intend to move away from odbc and use a different pattern for supporting different RDBMS products. However, my problem with solution implementation is 2 fold:
I want to write SQL code with parameters that conform to different back-ends, and so I want to be writing named parameters in my SQL now so that I don't have go back and re-do it later.
I don't want to rely on getting the order of my properties in line with my ?. This is bad. So my suggestion is to please add support for Named Parameters for odbc.
In the mean time I have hacked together a solution that allows me to do this with Dapper. Essentially I have a routine that replaces the named parameters with ? and also rebuilds the parameter object making sure the parameters are in the correct order.
However looking at the Dapper code, I can see that I've repeated some of what dapper is doing anyway, effectively it each parameter value is now visited once more than what would be necessary. This becomes more of an issue for bulk updates/inserts.
But at least it seems to work for me o.k...
I borrowed a bit of code from here to form part of my solution...
The ? for parameters was part of the solution for me, but it only works with integers, like ID. It still fails for strings because the parameter length isn't specifed.
OdbcException: ERROR [HY104] [Microsoft][ODBC Microsoft Access Driver]Invalid precision value
System.Data.Odbc. OdbcParameter.Bind(OdbcStatementHandle hstmt,
OdbcCommand command, short ordinal, CNativeBuffer parameterBuffer, bool allowReentrance)
System.Data.Odbc.OdbcParameterCollection.Bind(OdbcCommand command, CMDWrapper cmdWrapper, CNativeBuffer parameterBuffer)
System.Data.Odbc.OdbcCommand.ExecuteReaderObject(CommandBehavior behavior, string method, bool needReader, object[] methodArguments, SQL_API odbcApiMethod)
System.Data.Odbc.OdbcCommand.ExecuteReaderObject(CommandBehavior behavior, string method, bool needReader)
System.Data.Common.DbCommand.ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
Dapper.SqlMapper.QueryAsync(IDbConnection cnn, Type effectiveType, CommandDefinition command) in SqlMapper.Async.cs
WebAPI.DataAccess.CustomerRepository.GetByState(string state) in Repository.cs
var result = await conn.QueryAsync(sQuery, new { State = state });
WebAPI.Controllers.CustomerController.GetByState(string state) in CustomerController .cs
return await _customerRepo.GetByState(state);
For Dapper to pass string parameters to ODBC I had to specify the length.
var result = await conn.QueryAsync<Customer>(sQuery, new { State = new DbString { Value = state, IsFixedLength = true, Length = 4} });

how to execute MYSQL stored procedure in zend framework 2 with multiple result set

How to execute MYSQL stored procedure in zend framework 2 with multiple result set means if sp have multiple select query then how can i get all the result in array and how i pass dynamic value in sp for insert and update data in table.
thanks..
I recently wrote a small article about this. The solution I found is not a generic one and assumes that you are using PDO. I am not sure whether it works with other databases than MySQL. It is possible that there is a better and more generic way of doing this that I am not aware of.
$driver = $this->dbAdapter->getDriver();
$connection = $driver->getConnection();
$result = $connection->execute('CALL sp_get_profile_for_display (123)');
$statement = $result->getResource();
// Result set 1
$resultSet1 = $statement->fetchAll(\PDO::FETCH_OBJ);
foreach ($resultSet1 as $row) {
$something = $row->some_column;
}
// Result set 2
$statement->nextRowSet(); // Advance to the second result set
$resultSet2 = $statement->fetchAll(\PDO::FETCH_OBJ);
foreach ($resultSet2 as $row) {
/* Do something */
}
// Result set 3
$statement->nextRowSet(); // Advance to the third result set
$resultSet3 = $statement->fetchAll(\PDO::FETCH_OBJ);
foreach ($resultSet3 as $row) {
/* Do something */
}
Replace the 123 with the data you wish to pass to the stored procedure as a parameter. If using user supplied data, remember to escape it to prevent SQL injection!

I cannot get the output parameter when use function import by Entity Framework

Here's my SQL Server stored procedure :
ALTER PROCEDURE [dbo].[SearchUser]
(#Text NVARCHAR(100),
#TotalRows INT = 0 OUTPUT)
AS
BEGIN
SELECT #TotalRows=1000
SELECT * from Users
END
And my C# code
using (var context = new TestDBEntities())
{
var outputParameter = new ObjectParameter("TotalRows", typeof(Int32));
context.SearchUser("", outputParameter);
Response.Write(outputParameter.Value);
}
However outputParameter.Value always is null.
Could anybody tell me why?
Output parameters filled by its actual values during the execution of the stored procedure.
But table-valued stored procedure actually get executed only in moment when you're trying to iterate resulting recordset, but not calling a wrapper method.
So, this DOES'T work:
using (var context = new TestDBEntities())
{
var outputParameter = new ObjectParameter("TotalRows", typeof(Int32));
context.SearchUser("", outputParameter);
// Paremeter value is null, because the stored procedure haven't been executed
Response.Write(outputParameter.Value);
}
This DOES:
using (var context = new TestDBEntities())
{
var outputParameter = new ObjectParameter("TotalRows", typeof(Int32));
// Procedure does not executes here, we just receive a reference to the output parameter
var results = context.SearchUser("", outputParameter);
// Forcing procedure execution
results.ToList();
// Parameter has it's actual value
Response.Write(outputParameter.Value);
}
When you're working with stored procedures what don't return any recordset, they execute immediately after a method call, so you have actual value in output parameter.
We had a simular issue due to defered excecution our unit tests failed. In short if you have a stored proc that does NOT return anything you need to be sure to set the response type as 'None' when set as 'None' it will be excecuted when called and not defered.
In case you return anything (E.g. Scalar type of String results) it will excecute it when you use the result even if that .Count() or .ToList() is outside of the method that contains the function call.
So try not to force excecution if not need, when needed it should excecute but be sure to declare it correctly or it might not work.
I have same problem before. The main reason I think that the entities framework has the bug in case the user stored procedure has output parameter and return a result set. For example:
ALTER PROCEDURE [dbo].[SearchTest]
(
#RowTotal INT = 0 OUTPUT,
#RowCount INT = 0 OUTPUT
)
AS
BEGIN
SET NOCOUNT ON
SELECT * FROM SomeThing
SELECT #RowTotal = 1233, #RowCount = 5343
END
However if you change the user stored procedure as following, you can get the output params
ALTER PROCEDURE [dbo].[SearchTest]
(
#RowTotal INT = 0 OUTPUT,
#RowCount INT = 0 OUTPUT
)
AS
BEGIN
SET NOCOUNT ON
SELECT #RowTotal = 1233, #RowCount = 5343
END
You can workaround as following:
ALTER PROCEDURE [dbo].[SearchTest]
AS
BEGIN
DECLARE #RowTotal INT, #RowCount INT
SET NOCOUNT ON
SELECT #RowTotal = 1233, #RowCount = 5343
SELECT #RowTotal AS RowTotal, #RowCount AS RowCount, s.*
FROM SomeThing s
END
If anybody has better solution, please tell me

Resources