What is the alternative for System.Data.OracleClient.OracleCommand? - asp.net

Can anyone share a link to sample (ASP).Net code that uses the new Oracle Data Provider.Net library?
I have code a web application code that uses the System.Data.OracleClient classes and want to migrate to the new Oracle Data Provider for .Net.
Thanks

Your code might look as any standard ADO.NET code and you will be using an OracleConnection:
var connectionString = "Data Source=ORCL;User Id=user;Password=pwd;";
using (var conn = new OracleConnection(connectionString))
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "SELECT name FROM mytable";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
string name = reader.GetString(0);
// TODO: process the results here
}
}
}

There is no real difference in how they are used, unless you are doing weird stuff with In/Out parameters or cursors.
The difference that you would see in your code is that the namespace will change to Oracle.DataAccess. I believe that most of the type-names stayed the same.

Related

Passing a user defined table type to SQL function in Ormlite

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.

SQL Queries in ASP.NET

I am very new to ASP.NET. I have Visual Studio Express 2013 and MSSql Server that contains a bunch of databases. I watching a few tutorials about MVC/Entity framework to retrieve data from a table and display it. However, it is using Linq to SQL which I am not familiar with. All I need is to write a sql query to combine information in two tables and display it in the view. I could not find this simple tutorial on the internet. Can anyone give me a hint please?
To run a simple query you need to create a connection to the database like following:
var connection = new SqlConnection("your connecting string");
Once you have that you can connect to database and query using something called SqlCommand like following:
using (connection)
{
SqlCommand command = new SqlCommand(
"SELECT CategoryID, CategoryName FROM Categories;",
connection);
connection.Open();
//fetches the data by executing the command
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
//You can process data here , read it from reader and process it
// the index 0 and 1 indicate your query columns
var somedata = reader.GetInt32(0) + reader.GetString(1));
}
}
else
{
//no data returned from query
}
reader.Close();
}

How to use SQL-Server Stored Procedures?

over the past week or so I've been building an ASP site that connects to a Sql-Server 2008 database. I've never used Stored procedures and I was wondering if anyone could give me some guidance on how to create and how to use them within an ASP method. I'm trying to make the code of the website as simple and elegant as possible. Here's the code I'm trying to change into a stored procedure:
private void ExecuteInsert(string name, string type)
{
SqlConnection conn = new SqlConnection(GetConnectionStringHM());
string sql = "INSERT INTO tblSoftwareTitles (SoftwareName, SoftwareType) VALUES "
+"(#SoftwareName,#SoftwareSystemType)";
try
{
conn.Open();
SqlCommand cmd = new SqlCommand(sql, conn);
SqlParameter[] param = new SqlParameter[2];
//param[0] = new SqlParameter("#SoftwareID);
param[0] = new SqlParameter("#SoftwareName", SqlDbType.NVarChar, 200);
param[1] = new SqlParameter("#SoftwareType", SqlDbType.Int);
param[0].Value = name;
param[1].Value = type;
for (int i= 0; i < param.Length; i++)
{
cmd.Parameters.Add(param[i]);
}
cmd.CommandType = CommandType.Text;
cmd.ExecuteNonQuery();
}
catch (System.Data.SqlClient.SqlException ex)
{
string msg ="Insert Error:";
msg += ex.Message;
throw new Exception(msg);
}
finally
{
conn.Close();
}
}
This is just a Simple insert that takes two parameters from an entry form and inserts them into the database. Any Help with this would be much appreciated as I feel it would be a useful thing to know later on down the line. Thanks in advance!
You should look in to MSDN basics: http://msdn.microsoft.com/en-us/library/bb896274.aspx
You don't need to complicate things using for loop.
try
{
sqlConnection = new SqlConnection(dbConnectionString);
SqlCommand command = new SqlCommand(sql, sqlConnection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#SoftwareName", SqlDbType.NVarChar, 200).Value = SoftwareNameHere;
command.Parameters.Add("#SoftwareType", SqlDbType.Int).Value = SoftwareTypeHere;
sqlConnection.Open();
return command.ExecuteNonQuery();
}
catch (SqlException ex)
{
Console.WriteLine("SQL Error" + ex.Message.ToString());
return 0;
}
finally
{
conn.Close();
}
If you are using .NET 3.5 or above, you can use the USING code block which takes care of the disposal of your resources. I am not entirely sure, but from what I remember this was introduced with .NET 3.5 to replace Try/Finally code block (which required developers to dispose the resources like connection object manually through code).
using (SqlConnection con = new SqlConnection { dbConnectionString })
{
con.Open();
try
{
using (SqlCommand command = new SqlCommand { CommandType = CommandType.StoredProcedure, Connection = con, CommandTimeout = 300, CommandText = "sp_Test" })
{
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("#SoftwareName", SqlDbType.NVarChar, 200).Value = SoftwareNameHere;
command.Parameters.Add("#SoftwareType", SqlDbType.Int).Value = SoftwareTypeHere;
command.ExecuteNonQuery();
}
}
catch(SqlException ex)
{
//ex.ToString message here;
}
}
The answer you're looking for is at this SO post...
https://stackoverflow.com/a/4561443/1246574
The one thing I would improve upon for the accepted answer in that post, is the example in that answer doesn't use any USING statements. It would be better to have the connection and command within USING statements so they are automatically disposed.
Another approach would be to use the Microsoft Enterprise Library for interacting with your SQL Server DB. I think it's easier than using plain old SqlConnection and SqlCommand.
Since your code already uses parameters, you are 90% of the way there. All you have to do is:
Put the insert statement into a stored procedure, keeping the same parameter definitions as the dynamic statement.
Change CommandType.Text to CommandType.StoredProcedure
Change the command text to be just the name of the stored procedure.
Having done some reading on the subject I've come across some useful articles that really do question my need for stored procedures.
This article gives a good Viewpoint on how stored procedures can be more of a hassle than a help and are quite clunky and tedious in terms of coding, debugging ad error reporting.
http://www.codinghorror.com/blog/2004/10/who-needs-stored-procedures-anyways.html
And this article (linked in the one above) gives a good explanation on parametrized, explaining why they are necessary to reduce the risk of sql injections and also raises the point that these parametrized queries are cached in a similar way to procedures, giving them comparable performance gains
http://www.uberasp.net/getarticle.aspx?id=46
I feel that In my situation keeping parametrized sql Queries coded into my ASP pages will be the smartest move as these pages will be stored on a server and accessed by clients. I imagine if this were an application installed on several client machines hard coding the SQL wouldn't be a desirable option and so Stored procedures would be the best way to go (to my knowledge)
A follow Up to Stored procedures verses Parametrized sql can be found here with different links to each side of the argument if those are interested.
http://www.codinghorror.com/blog/2005/05/stored-procedures-vs-ad-hoc-sql.html
Hope this little answer helps out anyone else considering using stored procedures over parametrized SQL and vice-versa

Can Glimpse provide diagnostics when using the SqlClient namespace classes

I've downloaded Glimpse and the Glimpse.ADO extension and installed it on my test instance.
I thought I'd get a capture of any sql that was executed, but it seems like it doesn't capture commands with the way our code is written.
using (var conn = new SqlConnection(cString))
{
conn.Open();
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
cmd.CommandText = "Select count(*) from table";
cmd.CommandType = CommandType.Text;
txtResult2.Text = cmd.ExecuteScalar().ToString();
conn.Close();
}
I CAN get it to provide information from a test page with the sql code written like so:
var factory =DbProviderFactories.GetFactory(cString.ProviderName);
using (var connection = factory.CreateConnection())
{
connection.ConnectionString = connectionString.ConnectionString;
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText = "SELECT COUNT(*) FROM table";
command.CommandType = CommandType.Text;
txtResult1.Text = command.ExecuteScalar().ToString();
}
}
However I have too many places in my code to change if I can only capture data using this dbProviderFactories method.
Is there a way to get Glimpse.ADO to work with the System.Data.SqlClient.SqlConnection class? Is there another Glimpse extension that works with this namespace?
Is there another way to tackle this problem?
I agree with #StriplingWarrior, leveraging the provider factories will make your code more DRY and follow best practices. DbProviderFactories really is the best way to do this and your code won't explicitly rely on Glimpse.
However, if you really want to just move forward with your existing app code, Glimpse will support you with the following changes:
using (var conn = new GlimpseDbConnection(new SqlConnection(cString))
{
conn.Open();
DbCommand cmd = conn.CreateCommand();
cmd.CommandText = "Select count(*) from table";
cmd.CommandType = CommandType.Text;
txtResult2.Text = cmd.ExecuteScalar().ToString();
conn.Close();
}
In the example above, the command is created with the CreateCommand() method, which removes the need to associate the command and the connection.
Alternatively, you could also still explicitly create the command like so:
conn.Open();
DbCommand cmd = new GlimpseDbCommand(new SqlCommand());
cmd.Connection = conn;
cmd.CommandText = "Select count(*) from table";
cmd.CommandType = CommandType.Text;
Finally, more documentation about the SQL tab is available by clicking the ? icon in the Glimpse UI when you have the tab selected, or by going to our SQL documentation on getGlimpse.com. (I'll be adding this info to that page for future reference.)
In problems section on Glimpse site...
Getting Glimpse to work with manual created SQL Connections/Commands
http://getglimpse.com/Docs/Manual-ADO-Integration

Invalid cast exception on remote server Guid to string

I have this code in my project:
string userId = Membership.GetUser(username).ProviderUserKey.ToString();
SqlConnection conn = new SqlConnection(connectionString);
SqlCommand cmd = new SqlCommand("UPDATE aspnet_Membership SET IsLockedOut = 0, LastLockoutDate = #LastLockedOutDate WHERE UserId = #Userid", conn);
cmd.Parameters.Add("#LastLockedOutDate", SqlDbType.DateTime).Value = DateTime.Now;
cmd.Parameters.Add("#Userid", SqlDbType.VarChar, 255).Value = userId;
int rowsAffected = 0;
conn.Open();
rowsAffected = cmd.ExecuteNonQuery();
This works fantastic on my local machine. The user gets unlocked no problem. But for some reason when I deploy it to a demo site on the remote server I get this error:
InvalidCastException: Failed to convert parameter value from a Guid to a String
It's failing on the cmd.ExecuteNonQuery line. I tried changing the parameter to a uniqueidentifier and passing the actual guid but that didn't work either.
Anybody know why this would work locally but not on a remote server? Or know of a way I can modify the code to possibly work?
Rather than trying to manually unlock the user could you not use :-
var oUser = Membership.GetUser(username);
oUser.UnlockUser();
Membership.UpdateUser(oUser);
This allows the .NET process to do all the heavy lifting for you.
[Edit to answer the original question]
Guid gUserID = (Guid)Membership.GetUser(username).ProviderUserKey;
if (gUserID != Guid.Empty)
{
using (
var oConn =
new SqlConnection(connectionString)
{
oConn.Open();
using (SqlCommand oCmd = oConn.CreateCommand())
{
oCmd.CommandType = CommandType.Text;
oCmd.CommandText = "UPDATE aspnet_Membership SET IsLockedOut = 0, LastLockoutDate = #LastLockedOutDate WHERE UserId = #gUserID";
oCmd.Parameters.Add(new SqlParameter("#gUserID", gUserID));
oCmd.Parameters.Add(new SqlParameter("#LastLockedOutDate", DateTime.UtcNow));
oCmd.ExecuteNonQuery();
}
}
}
It may also be worth changing your DateTime.Now to DateTime.UtcNow so that if you ever have to move timezones or share with other machines out of your location you are all on a equivilent time.
If you get an error thrown on the ProviderUserKey then chances are either the user doesn't exist or the UserID isn't a GUID after all.
Maybe you can try something like
cmd.Parameters.Add("#Userid", SqlDbType.Guid).Value = new Guid(userId);
Sorry for the lame answering my own question but I resolved this. I stripped the custom membership provider out and just used the default membershipUser.UnlockUser(); and it works great. The custom provider wasn't actually doing anything anyway. I think it was developed for features that aren't being used anymore.

Resources