Passing a user defined table type to SQL function in Ormlite - ormlite-servicestack

I've to pass a table to a SQL function (till now I've passed to stored procedures and everything was fine)
Consider the following snippet
var dataTable = new DataTable();
dataTable.Columns.Add(new DataColumn("ID", typeof(Guid)));
foreach (var o in orders)
{
var r = dataTable.NewRow();
r["ID"] = o;
dataTable.Rows.Add(r);
}
var res = db.Exec(cmd =>
{
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add(new SqlParameter("INPUT", dataTable));
cmd.CommandText = "SELECT * FROM FUNCTION";
return cmd.ConvertToList<MyObj>();
});
I'm not aware if parameters are considered when specifing CommandType as Text, I've tried on SQLServer and it works...
What am I doing wrong? is this a limitation of ServiceStack's OrmLite?
Thanks

When manually populating cmd as in your example you're using ADO.NET (i.e. not OrmLite), so you need to find out the correct way to call a SQL Server function from ADO.NET.
It seems you can only pass a datatable to a UDF from SQL Server 2008+ and requires that your TableType parameter is READONLY.

Related

Convert date in SQLite?

I created an scheduler application with SQL server and now i want to make another one using SQLite. I have a convert query in SQL and it does not work in SQLite. Can anyone help?
try
{
ObservableCollection<Classes.EventClass> listEvents = new ObservableCollection<EventClass>();
SQLiteConnection conn = new SQLiteConnection(#"Data Source=Scheduler.db;Version=3;");
string query= "Select * from Sche_Event where CONVERT(DATE,Event_TimeFrom) = CONVERT(DATE,'" +d.ToString("yyyy-MM-dd HH:mm:ss") + "') ORDER BY Event_TimeFrom ASC";
SQLiteCommand command= new SQLiteCommand(query, conn);
conn.Open();
SQLiteDataReader dr = command.ExecuteReader();
while (dr.Read())
{
EventClass dog = new EventClass();
dog.DogID = dr.GetInt32(0);
dog.DogName = dr.GetString(1);
dog.DogText = dr.GetString(2);
dog.DogPriority = dr.GetInt32(3);
dog.DogTimeFrom = dr.GetDateTime(4);
dog.DogTimeTo = dr.GetDateTime(5);
dog.KliID = dr.GetInt32(6);
listEvents .Add(dog);
}
return listEvents ;
}
catch (Exception)
{
return null;
}
I expect that my code goes to While() and read the information about the Event but all it does it goes to Catch() and returns nothing.
The query in SQL works just fine but i dont not work with SQLite :(
Of course the statement doesn't work in SQLite, because convert() is not a known function there. But if you're lucky you don't even need it, depending on the format in which the timestamp is stored in your SQLite table. As you didn't provide any sample data nor described what you actually want to do, you could either read the SQLite doc about date and time functions or rephrase your question to "How do I do X in SQLite?".

SQL Server User-Defined Table Type and .NET

I had a need to pass an integer array to a stored procedure from .NET and so I googled the topic and eventually ran across Arrays and Lists in SQL Server 2008, written by Erland Sommarskog and supposedly considered the standard manner in which one goes about this process.
I've tried two different manners to pass a user-defined table type to a stored procedure, but I'm getting exceptions with each one. Both of these manners are similar to what Erland Sommarskog uses in the link above.
Manner #1 - Use DataTable as SqlParameter
DataTable dt = new DataTable();
dt.Columns.Add("n", typeof(int));
// Just adding 3 test rows to the DataTable
DataRow dr = dt.NewRow();
dr["n"] = 1;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["n"] = 2;
dt.Rows.Add(dr);
dr = dt.NewRow();
dr["n"] = 3;
dt.Rows.Add(dr);
// Creation of the SqlParameter
SqlParameter p = new SqlParameter();
p.ParameterName = "#ids";
p.Direction = ParameterDirection.Input;
p.SqlDbType = SqlDbType.Structured;
p.TypeName = "lstInt_TblType";
p.Value = dt;
// Blows up here
DataSet ds = DAWrapper.GetDataSet(
Common.GetDB(),
"usp_Test",
new SqlParameter[] { p });
The exception that I get states:
The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Parameter 1 ("#ids"): Data type 0x62 (sql_variant) has an invalid type for type-specific metadata.
Manner 2 - Use List as SqlParameter
List<SqlDataRecord> lstSDR = new List<SqlDataRecord>();
SqlMetaData[] tvp_definition = { new SqlMetaData("n", SqlDbType.Int) };
// Just adding 3 test rows
SqlDataRecord rec = new SqlDataRecord(tvp_definition);
rec.SetInt32(0, 50);
lstSDR.Add(rec);
rec = new SqlDataRecord(tvp_definition);
rec.SetInt32(0, 51);
lstSDR.Add(rec);
rec = new SqlDataRecord(tvp_definition);
rec.SetInt32(0, 52);
lstSDR.Add(rec);
// Creation of the SqlParameter
SqlParameter p = new SqlParameter();
p.ParameterName = "#ids";
p.Direction = ParameterDirection.Input;
p.SqlDbType = SqlDbType.Structured;
p.TypeName = "lstInt_TblType";
p.Value = lstSDR;
// Blows up here
DataSet ds = DAWrapper.GetDataSet(
Common.GetDB(),
"usp_Test",
new SqlParameter[] { p });
And the exception that I get for this ones states:
No mapping exists from object type System.Collections.Generic.List`1[[Microsoft.SqlServer.Server.SqlDataRecord, System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] to a known managed provider native type.
Other Info
lstInt_TblType is the User-Defined Table Type in my SQL Server 2008. It does exist (I triple-checked this!). It has one column called "n", of type int, primary key and doesn't allow nulls. I copied exactly how Erland set his up.
I also verified that the stored procedure usp_Test works from SQL Server Manager Studio, so I'm fairly certain that the exceptions are not issuing from that direction. This is the t-sql that I used to verify that the stored procedure works:
DECLARE #ids lstInt_TblType
INSERT #ids(n) VALUES(1),(2),(3)
EXEC usp_Test ids
Any suggestions on where to go with this would be greatly appreciated. Thanks!
*EDIT: *
The stored procedure usp_Test:
ALTER PROCEDURE [dbo].[usp_Test]
(
#ids lstInt_TblType READONLY
)
AS
BEGIN
SET NOCOUNT ON;
select *
from dbo.dat_MetaData
where MetaDataTypeID in (select n from #ids)
END
GO
Found a different way to go about doing it. This way uses the System.Data.SqlClient libraries to create a connection to the database, specify the stored procedure name, and then pass a parameter in as a DataTable that serves as the SQL Server user-defined table type.
using (SqlConnection conn = new SqlConnection(connStr)) {
SqlCommand cmd = conn.CreateCommand();
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "dbo.usp_Test";
cmd.Parameters.AddWithValue("#ids", dt);
conn.Open();
using (SqlDataReader sqlReader = cmd.ExecuteReader()) {
DataTable retTbl = new DataTable();
retTbl.Load(sqlReader);
}
}
You can also find good examples of how to pass table-valued parameter data to a stored procedure in Microsoft's own Table-Valued Parameters reference.

Oracle query/ stored procedure to return multiple resultsets

I am using oracle database. When I tried to fetch the data using a single select query, it returned a single table in the dataset.
How to write a select query or procedure in oracle, where I can get a dataset with 2-3(multiple) tables?
As far as I understood you question you would like to reduce the round trips to your database.
This can be done by a stored procedure in the following way:
http://msdn.microsoft.com/en-us/library/ms971506.aspx#msdnorsps_topic6
Package header:
CREATE OR REPLACE PACKAGE SELECT_JOB_HISTORY AS
TYPE T_CURSOR IS REF CURSOR;
PROCEDURE GetJobHistoryByEmployeeId
(
p_employee_id IN NUMBER,
cur_JobHistory OUT T_CURSOR
);
END SELECT_JOB_HISTORY;
Package:
CREATE OR REPLACE PACKAGE BODY SELECT_JOB_HISTORY AS
PROCEDURE GetJobHistoryByEmployeeId
(
p_employee_id IN NUMBER,
cur_JobHistory OUT T_CURSOR
)
IS
BEGIN
OPEN cur_JobHistory FOR
SELECT * FROM JOB_HISTORY
WHERE employee_id = p_employee_id;
END GetJobHistoryByEmployeeId;
END SELECT_JOB_HISTORY;
Client:
// create connection
OracleConnection conn = new OracleConnection("Data Source=oracledb;
User Id=UserID;Password=Password;");
// create the command for the stored procedure
OracleCommand cmd = new OracleCommand();
cmd.Connection = conn;
cmd.CommandText = "SELECT_JOB_HISTORY.GetJobHistoryByEmployeeId";
cmd.CommandType = CommandType.StoredProcedure;
// add the parameters for the stored procedure including the REF CURSOR
// to retrieve the result set
cmd.Parameters.Add("p_employee_id", OracleType.Number).Value = 101;
cmd.Parameters.Add("cur_JobHistory", OracleType.Cursor).Direction =
ParameterDirection.Output;
// open the connection and create the DataReader
conn.Open();
OracleDataReader dr = cmd.ExecuteReader();
// output the results and close the connection.
while(dr.Read())
{
for(int i = 0; i < dr.FieldCount; i++)
Console.Write(dr[i].ToString() + ";");
Console.WriteLine();
}
conn.Close();
If you have to join these tables you can also use a normal join and split the result on the client (imho this is the way how a lot of ORMs do it).
This is exactly what I did, it was quite simple :
Database db = DatabaseFactory.CreateDatabase("ConnectionString");
object[] results = new object[3];
DbCommand cmd = db.GetStoredProcCommand("DATABASE.SELECT_JOB_HISTORY.GetJobHistoryByEmployeeId",results);
DataSet ds = db.ExecuteDataSet(cmd);
DataTable dt1 = ds.Tables[0];
DataTable dt2 = ds.Tables[1];

Parameterized query in Oracle trouble

I'm using Oracle.DataAccess rather than the obsolete System.Data.OracleClient and I seem to be having trouble passing multiple parameters to my update query
This works
OracleCommand.CommandText = "UPDATE db SET column1 = :param1 WHERE column2 = 'Y'"
OracleCommand.Parameters.Add(New OracleParameter("param1", "1234"))
But I want to be able to pass multiple parameters
Here's my full code
OracleConn.Open()
OracleCommand = OracleConn.CreateCommand()
OracleCommand.CommandText = "UPDATE db SET column1 = :param1 WHERE column2 = :param2"
OracleCommand.CommandType = CommandType.Text
OracleCommand.Parameters.Add(New OracleParameter("param1", "1234"))
OracleCommand.Parameters.Add(New OracleParameter("param2", "Y"))
OracleCommand.ExecuteNonQuery()
My SELECT query seems to work when passing multiple parameters but not the update one
Although I can't see anything wrong with your example, I wonder if you're being hit by the old BindByName problem. By default, ODP.NET binds parameters to the query in the order in which they are added to the collection, rather than based on their name as you'd like. Try setting BindByName to true on your OracleCommand object and see if that fixes the problem.
I've had this problem so many times that I use my own factory method to create commands which automatically sets this property to true for me.
Classic useless Oracle documentation here
To emulate the default behavior of the System.Data.OracleClient, you should set the OracleCommand to bind by name.
OracleCommand.BindByName = True
Try newing up your OracleParameter with a the type specified. Set the value of the object before adding it to the parameters list.
var param1 = new OracleParameter( "param1", OracleType.Int32 );
param1.Value = "1234";
OracleCommand.Parameters.Add( param1 );
Try this, hope it works. It does compile.
Not sure if you also have to send a commit...
I always do this sort of thing through a stored procedure, so I have a commit after the update statement in the stored procedure.
Harvey Sather
OracleConnection ora_conn = new OracleConnection("connection string");
OracleCommand ora_cmd = new OracleCommand("UPDATE db SET column1 = :param1 WHERE column2 = :param2", ora_conn);
ora_cmd.CommandType = CommandType.Text;
ora_cmd.BindByName = true;
ora_cmd.Parameters.Add(":param1", OracleDbType.Varchar2, "1234", ParameterDirection.Input);
ora_cmd.Parameters.Add(":param2", OracleDbType.Varchar2, "Y", ParameterDirection.Input);
ora_cmd.ExecuteNonQuery();
The first code block is correct: use a colon in front of the parameter name, but not in the first argument to OracleParameter.
If no errors are thrown, it could be that the UPDATE runs successfully, it just doesn't update any records based on the WHERE clause and its substituted parameter value. Try doing it on a test table with no WHERE clause in the UPDATE to make sure it does something.
Here's the type of structure I usually use (sorry, this is from memory) :
int rows = 0;
using ( OracleConnection conn = new OracleConnection(connectionString) ) {
using ( OracleCommand cmd = conn.CreateCommand() ) {
cmd.CommandText = "UPDATE table SET column1 = ':p1 WHERE column2 = :p2";
cmd.CommandType = CommandType.Text;
cmd.Parameters.AddWithValue(":p1", p1Val);
cmd.Parameters.AddWithValue(":p2", p2Val);
rows = cmd.ExecuteNonQuery();
}
}
The key difference is the use of the AddWithValue - I don`t remember why I ended up using that, but do remember having problems with some of the other ways of doing it.

MySQL / ASP.NET Stored Procedures

Hopefully this is not a ServerFault question...
I'm working forward on migrating a project from storing data in XML Serialization to a MySQL database. I'm using the example provided me from a previous question answered yesterday.
Connecting using phpMyAdmin and MySQL Workbench I've created a Stored Procedure called 'sprocOrderSelectSingleItem'. It seems to work well with MySQL for all I can tell. When I run the SHOW CREATE PROCEDURE sprocOrderSelectSingleItem it returns the following:
CREATE DEFINER=username#% PROCEDURE sprocOrderSelectSingleItem(IN orderID INTEGER)
BEGIN SELECT * FROM tblOrders WHERE ID=orderID; END
My cooperative ASP.NET code goes something like this:
public static Order GetItem(int ID)
{
Order objOrder = null;
using (OdbcConnection objConnection = new OdbcConnection(Utils.ApplicationConfiguration.ConnectionString))
{
OdbcCommand objCommand = new OdbcCommand("sprocOrderSelectSingleItem", objConnection);
objCommand.CommandType = CommandType.StoredProcedure;
objCommand.Parameters.AddWithValue("orderID", ID);
objConnection.Open();
using (OdbcDataReader objReader = objCommand.ExecuteReader())
{
if (objReader.Read())
{
objOrder = FillDataRecord(objReader);
}
objReader.Close();
}
objConnection.Close();
}
return objOrder;
}
When I view the page I get the following error message:
ERROR [42000] [MySQL][ODBC 5.1 Driver][mysqld-5.0.77]You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'sprocOrderSelectSingleItem' at line 1
Really not catching on to what could be missing or going wrong. Are there any additional tests I should/could be running to confirm things are working on the MySQL side? Am I missing a step to pass the Stored Procedure call correctly in ASP.NET? The code breaks at the line of:
using (OdbcDataReader objReader = objCommand.ExecuteReader())
Replacing the line of
OdbcCommand objCommand = new OdbcCommand("sprocOrderSelectSingleItem", objConnection);
with this instead
OdbcCommand objCommand = new OdbcCommand("SELECT * FROM tblOrders WHERE ID=" + ID + ";", objConnection);
and everything works as expected.
Thanks for any help you guys can provide.
Your can run an execute on sprocOrderSelectSingleItem in Mysql directly with the ID parameter.
It will show that your StoredProc run correctly.
Here is a sample code in C# that call a stored proc.
OdbcCommand salesCMD = new OdbcCommand("{ CALL SalesByCategory(?) }", nwindConn);
salesCMD.CommandType = CommandType.StoredProcedure;
OdbcParameter myParm = salesCMD.Parameters.Add("#CategoryName", OdbcType.VarChar, 15);
myParm.Value = "Beverages";
OdbcDataReader myReader = salesCMD.ExecuteReader();
Look at the "Call" in the OdbcCommand and the "?" for the parameter that is later supplied with a value.
Can you try something like below:
OdbcCommand cmd = new OdbcCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "{call LoadCustCliOrders(?,?,?,?)}";
cmd.Parameters.Add("CUST_ID",OdbcType.Int);
cmd.Parameters.Add("CLIENT_ID",OdbcType.Int);
cmd.Parameters.Add("DATE_FROM",OdbcType.Date);
cmd.Parameters.Add("DATE_TO",OdbcType.Date);
...
cmd.Parameters["CUST_ID"].Value = _CustId;
cmd.Parameters["CLIENT_ID"].Value = _ClientId;
cmd.Parameters["DATE_FROM"].Value = _DateFrom;
cmd.Parameters["DATE_TO"].Value = _DateTo;
cmd.ExecuteReader
Are you sure that you are using the same username or user with the same access privileges.
I think you need to add the word "CALL" before the stored proc.
It should be CALL sprocOrderSelectSingleItem and try.

Resources