MS SQL Server Update in C# - c#

Im trying to update a table in C#
int record_id = 123;
using (SqlConnection connection = new SqlConnection(sqlServer)) {
SqlCommand mySqlCommand;
string sql = "UPDATE my_table SET foo = #foo WHERE id = #id;";
connection.Open();
mySqlCommand = connection.CreateCommand();
mySqlCommand.CommandText = sql;
mySqlCommand.Parameters.Add("#foo", SqlDbType.VarChar, 50);
mySqlCommand.Parameters["#foo"].Value = "bar";
mySqlCommand.Parameters.Add("#id", SqlDbType.VarChar, 50);
mySqlCommand.Parameters["#id"].Value = record_id;
mySqlCommand.ExecuteNonQuery();
connection.Close();
}
When executed, I get a 500 server error with the following message:
----- The page cannot be displayed because an internal server error has occurred. Most likely causes:
IIS received the request; however, an internal error occurred during
the processing of the request. The root cause of this error depends on
which module handles the request and what was happening in the worker
process when this error occurred.
IIS was not able to access the web.config file for the Web site or
application. This can occur if the NTFS permissions are set
incorrectly.
IIS was not able to process configuration for the Web site or
application. The authenticated user does not have permission to use
this DLL.
The request is mapped to a managed handler but the .NET Extensibility
Feature is not installed.
Im not really a C#/.NET developer and not certain about the syntax here. I do know that the line mySqlCommand.ExecuteNonQuery() causes the error.
There are also other SQL requests on the page (that I did not write) and they execute without issues. Unfortunately, none of them are update requests that I can use as an example.

Related

SQL Query works in SSMS but not in C#: SELECT denied

To begin with: It is not a particular statement that does not work. SELECT * FROM [TABLE]; does not work either. When I run it in SSMS as user A it works perfectly fine. When I use it in C# like this:
string sqlCommand = "SELECT * FROM [TABLE];"
using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["Name"].ToString()))
using (var command = new SqlCommand(sqlCommand, conn))
{
conn.Open();
using (var dataReader = command.ExecuteReader())
{
while (dataReader.Read())
{
// work with results
}
}
}
I log this code block with a try-catch and I get this error message: System.Data.SqlClient.SqlException (0x80131904): The SELECT permission was denied on the object 'TABLE', database 'MyDb', schema 'dbo'.
Even if I run the program on the server where the db is, I get the same error.
My connection string looks loke this:
Data Source=Server\Something;Initial Catalog=MyDb;User ID=DOMAIN\username;Password=verySecurePassword;Trusted_Connection=True;
User A has the datareader role on the entire db.
Do you have any idea why this might be? My db admins cannot help me either and it does not appear to be a network issue, as the connection seems to work.
When you have this in your connection string:
Trusted_Connection=True;
This part of the connection string is ignored:
User ID=DOMAIN\username;Password=verySecurePassword;
Trusted connections and integrated security mean you always connect to the server as the account running your program's process. You don't get to specify the password; instead, the program will pass the authentication token issued for the user running the process, and the database will validate against that token.
If you need to use a domain login, you must run your program as that user. If you need to use a username/password, you must use Sql authentication with a non-domain account defined in Sql Server.

C# Run MySQL Update Query as Localhost user

I'm working on a .NET WebForms C# website and I normally use SQL Server but I have a project which is requiring use of a MySQL database, and I'm able to resolve most problems but not this last one: I can't run updates on a database or I get an error. The error I'm getting is this:
UPDATE command denied to user 'xxxx'#T'mymachine' for table 'pages'
The advice I was given to overcome this is as follows:
You need to express the login as xxxx#localhost and run it on the database server (MySQL users are bound to localhost on that server)
Slight issue is... I can't find any advice on how to express a login as a localhost user, or how to run a query as a localhost user. It defaults to xxxx#mymachine, rather than xxxx#localhost, which is why it doesn't work. Could anyone help me with how to run a query as a localhost user?
For my queries I'm connecting using the following:
Server=00.00.00.00;Database=(databasename);Uid=xxxx;Pwd=(password);
My query is a rather simple one:
MySqlConnection connection = null;
try
{
var query =
string.Format(
"UPDATE pages SET approvedDate = {1} WHERE id = {0};",
pageId, approvedDate);
connection = new MySqlConnection(Settings.Default.ConnectionString);
connection.Open();
var command = new MySqlCommand(query, connection)
{
CommandType = CommandType.Text
};
command.ExecuteNonQuery();
}
catch (Exception ex)
{
(exceptionstuff)
}
finally
{
connection?.Close();
}
Any help would be hugely appreciated.
Edit:
To stop you needing to read the comments for this, the first thing I tried was changing the username to xxxx#localhost, like this:
Server=00.00.00.00;Database=(databasename);Uid=xxxx#localhost;Pwd=(password);
and I got this error instead:
Access denied for user xxxx#localhost#mymachine

Restarts c# windows service on a url call

I have a c# application which runs as a windows service. This application uses open source tiny http server for URL communications. There is a flext application developed to update and select the data from sqlite database via c# application using get/post methods.
I have a url called https:/domainname:portnumber/folder/tree/200
which reads data from database with the help of a c# service and returns a huge amount of data in xml form to the client.
Some times when this url gets called totral c# windows service is getting restarted.
And then needs to refresh the flext application to start it again.
The server firewall where the windows service is installed is turned off and the machine is also reachable.
When I checked log I found after this url call, the server restarts. Also, when I checked the traffic in fiddler I got the error below:
HTTP/1.1 502 Fiddler - Connection Failed
Content-Type: text/html; charset=UTF-8
Connection: close
Timestamp: 10:18:52.685
[Fiddler] The socket connection to (domainname) failed. <br />ErrorCode: 10061.
The code used for calling this folder/tree is below
public string Tree()
{
try
{
string langstr = "";
if (Request.QueryString["lang"] != null && !string.IsNullOrEmpty(Request.QueryString["lang"].Value))
{
langstr = Request.QueryString["lang"].Value.ToString();
}
else
{
ThingzDatabase db = SessionDatabase;
langstr = db.DefaultLanguage;
db = null;
}
folderTree = new FolderTree(Convert.ToInt32(Id), true, SessionDatabase, langstr);
XmlDocument doc = folderTree.XML;
Response.ContentType = ContentType.Xml;
langstr = null;
folderTree.db2 = null;
folderTree = null;
//GC.Collect();
return doc.InnerXml;
}
catch (Exception e)
{
TouchServer.Log(Logger.MessageType.Error, 1, e.ToString());
return "Get folder tree failed, reason:" + e.Message;
}
}
To execute the query from sqlite database the code below is used
public SQLiteDataReader ExecuteSQL(String sqlExpr)
{
if (conn.State != ConnectionState.Open
Open(DataFile);
using (SQLiteCommand cmd = conn.CreateCommand())
{
cmd.CommandText = sqlExpr + ";PRAGMA read_uncommitted = 1;";
cmd.CommandType = CommandType.Text;
return cmd.ExecuteReader();
}
}
Whats the size of the return string? You could write it to a file to verify the length of the return string.
There may be problems with web service if the length exceeds certain limit.
The following link discusses similar problem.
http://social.msdn.microsoft.com/forums/en-US/wcf/thread/58e420e9-43a3-4119-b541-d18158038e36/
The Service may crash if you have not handled the exception.
In that service, that is sending a big bunch of text over http; when writing to the reponse add response.BufferOutput = false; at the beginning of the method and call Flush after every some writes.
Note: I am not sure if this works in your embedded http server. But this works for IIS.
It looks as if your SQL code is not catching exceptions... At least not immediately within the method. It stands to reason that if an exception were thrown, the service would crash due to the unhandled exception. Try hooking into the AppDomain.UnhandledException event and printing any caught exceptions to a file, log source, etc. This will allow you to determine if SQL exceptions (read timeouts, etc.) are causing the crash.

Multiple session-less requests to a page (which interacts with database) results in HTTP Error 500

I have an asp.net web page which interacts with a SQL Server database, grabs some data and then returns an XML response (which I feed into Freeswitch using xml_curl).
Because Freeswitch (FS from now on) does not store cookies, each request creates a new session.
When the number of requests gets too much (about 97 to 100), the SqlConnection.Open() method gets timeout from the SQL Server Instance, which then results in HTTP Error 500.
To test my assumption, I have created a small script using PHP and cURL, which make repeated requests to my asp.net page. If I store cookies (and thus sessions) in the PHP script I can make 10000 successful requests in almost 314 seconds.
But without sessions, I get stuck at about 97~100 requests, and then I get HTTP Error 500.
Is there anyway to overcome this problem?
==Edit==
Here is how I interact with the database:
String connectionString = WebConfigurationManager.ConnectionStrings["SqlServerConnection"].ConnectionString;
SqlConnection connection = new SqlConnection(connectionString);
SqlCommand command = connection.CreateCommand();
command.CommandType = CommandType.Text;
command.CommandText = "Select * from dbo.Template where Name = '" + name + "'";
Template template = new Template();
connection.Open();
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
reader.Read();
template.Name = reader["Name"].ToString();
template.XMLContent = reader["XMLContent"].ToString();
}
else
{
template.Name = "";
template.XMLContent = "";
}
reader.Close();
connection.Close();
return template;
And the Template table has these fields:
ID => int, identity, primary key
Name => nvarchar(255), unique
XMLContent => ntext
It appears you are using a connection pool. By default these pools have a max of 100 connections to your SQL server and queue any additional connections. The queue has a timeout (default 15 seconds) which can be extended if you wish to queue your requests longer. This means that you might get backed up on your server. You can also increase the pool max size if your SQL server can handle it.
Here is how you increase your connection settings by adding these parameters:
Timeout=60
Max Pool Size=150
etc etc
Some steps to impove this code.
If you do not need session, disabled it for this page so not cookie is going to be made.
Use some cache here base on the name If the request for name is the same, get it from cache and not open the database
Use a static variable to read only one time the connection string.
Place it on [try catch | using] , to be sure that you close the connection in case of failure
Maybe you can try a mutex lock logic, to avoid too many request together.
Use parameters on your sql call.
In addition to #Aristos suggestions:
Use Async-Pages!
Example and "Benchmark"
Some time ago I asked nearly the same question here on so

Right code to retrieve data from sql server database

I have some problems in database connection and wonder if I have something wrong in my code. Please review. This question is related: Switch between databases, use two databases simultaneously question.
cs="Data Source=mywebsite.com;Initial Catalog=database;User Id=root;Password=toor;Connect Timeout=10;Pooling='true';"
using (SqlConnection cnn = new SqlConnection(WebConfigurationManager.ConnectionStrings["cs"].ConnectionString))
{
using (SqlCommand cmmnd = new SqlCommand("", cnn))
{
try
{
cnn.Open();
#region Header & Description
cmmnd.Parameters.Add("#CatID", SqlDbType.Int).Value = catId;
cmmnd.CommandText = "SELECT UpperID, Title, Description FROM Categories WHERE CatID=#CatID;";
string mainCat = String.Empty, rootCat = String.Empty;
using (SqlDataReader rdr = cmmnd.ExecuteReader())
{
if (rdr.Read())
{
mainCat = rdr["Title"].ToString();
upperId = Convert.ToInt32(rdr["UpperID"]);
description = rdr["Title"];
}
else { Response.Redirect("/", false); }
}
if (upperId > 0) //If upper category exists add its name
{
cmmnd.Parameters["#CatID"].Value = upperId;
cmmnd.CommandText = "SELECT Title FROM Categories WHERE CatID=#CatID;";
using (SqlDataReader rdr = cmmnd.ExecuteReader())
{
if (rdr.Read())
{
rootCat = "<a href='x.aspx'>" + rdr["Title"] + "</a> ยป ";
}
}
}
#endregion
#region Sub-Categories
if (upperId == 0) //show only at root categories
{
cmmnd.Parameters["#CatID"].Value = catId;
cmmnd.CommandText = "SELECT Count(CatID) FROM Categories WHERE UpperID=#CatID;";
if (Convert.ToInt32(cmmnd.ExecuteScalar()) > 0)
{
cmmnd.CommandText = "SELECT CatID, Title FROM Categories WHERE UpperID=#CatID ORDER BY Title;";
using (SqlDataReader rdr = cmmnd.ExecuteReader())
{
while (rdr.Read())
{
subcat.InnerHtml += "<a href='x.aspx'>" + rdr["Title"].ToString().ToLower() + "</a>\n";
description += rdr["Title"] + ", ";
}
}
}
}
#endregion
}
catch (Exception ex) { HasanG.LogException(ex, Request.RawUrl, HttpContext.Current); Response.Redirect("/", false); }
finally { cnn.Close(); }
}
}
The random errors I'm receiving are:
A transport-level error has occurred when sending the request to the server. (provider: TCP Provider, error: 0 - An existing connection was forcibly closed by the remote host.)
A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)
Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
Cannot open database "db" requested by the login. The login failed. Login failed for user 'root'.
There's no real issues here.
You don't need the extraneous finally { cnn.close(); } as the using clause will take care of that for you. However changing it will have exactly zero impact.
Another thing is that I would put the try .. catch outside of the using clause with a redirect. But, again, I don't think that would affect the dispose from being called.
It's interesting that you would get connection pool errors (timeout expired) if you are always properly disposing of your connections, as you've shown.
Which leaves us with only one real solution: switch hosting providers. They have either overloaded their DB server to the point of unusability or some hardware element in their network setup (nic, switch, router, etc) is bad and dropping packets.
There are couple of inconsistencies which need to fixed:
description = rdr["Title"]; no proper casting defined.
Same command object is used for each sql statement and even you are not clearing parameters, it would be ideal if a separate command should be used for each sql statement.
Too many redirections as well, it is best to handle redirection at the end of method.
Check the database server health as well, it looks like database server is not responsive enough.
Hope it will help.
If you're connecting remotely to a database provider, you need to look at several possibilities like your own network configuration, firewall setup, etc.
Use a packet sniffer to figure out if lost packets are the issue.
Connection pooling is setup on your local machine, the server making the connections. If the database provider only allows for 5 connections and your connection pool is setup for 50 connections, well... you can do the math. It looks like you're closing the connections properly, so no issues there.
True... one error on "description = rdr["Title"];", should that be "description = rdr["Description"].ToString()"?
No need to put a using statement around the SqlCommand object and since you're using ad-hoc queries, just use string.Format("sql test {0}", param). This way, you can reuse the SqlCommand object without having to clear the parameters.
The biggest issue I see here is that you've mixed the presentation layer with the business layer with the datasource layer. Dump the try...catch and allow the business layer to handle logging stuff. Return an object to the presentation layer and allow it to perform the redirects. Keep the datasource layer very simple... get the data and return an entity. The business layer can handle any business logic on the entity itself.
SQL Server not found could be your fault or the providers... if the provider is at fault often, change providers.
Are you sure that the DB is configured to grant remote access using TCP?

Categories

Resources