I am wondering if there is an elegant way to check for the existence of a DB? In brief, how do test the connection of a db connection string?
Thanks
Set the Initial Catalog=master in the connection string and execute:
select count(*) from sysdatabases where name = #name
with #name set to the name of the database.
If you want to check the connection string as a whole (and not existence of an independent database), try connecting to it in a try/catch block.
To cover the range of possibilities (server doesn't exist, database doesn't exist, no login, no permissions, server down, etc) - the simplest idea is simply to try to connect as normal, and perform something trivial - SELECT GETDATE() for example. If you get an exception, there is a problem!
There are times (especially when dealing with out-of-process systems) when try/catch is the most pragmatic option.
You could just try connecting to it. If it throws an exception, then the connection string is bad in some way, either the database doesn't exist, the password is wrong, or something else.
DbConnection db = new SqlConnection(connection_string);
try
{
db.Open();
}
catch ( SqlException e )
{
// Cannot connect to database
}
Just try a DBConnection.Open() wrapped in a try block catching DBException.
About as elegant a solution as you are going to find.
try
IF NOT EXISTS(SELECT * FROM sys.databases WHERE [name] = #name)
CREATE DATABASE #name;
GO
or
IF db_id(#name) IS NOT NULL
CREATE DATABASE #name;
GO
or SqlConnection.ChangeDatabase(String). I think it could use less sql server resources then new connection attempt.
If you're using Entity Framework or have it available to you, you can simply call Database.Exists():
if (Database.Exists(connectionString))
{
// do something
}
else
{
// do something else
}
This is what worked for me to verify the existence of any Postgres database with C#:
private bool chkDBExists(string connectionStr, string dbname)
{
using (NpgsqlConnection conn = new NpgsqlConnection(connectionStr))
{
using (NpgsqlCommand command = new NpgsqlCommand
($"SELECT DATNAME FROM pg_catalog.pg_database WHERE DATNAME = '{dbname}'", conn))
{
try
{
conn.Open();
var i = command.ExecuteScalar();
conn.Close();
if (i.ToString().Equals(dbname)) //always 'true' (if it exists) or 'null' (if it doesn't)
return true;
else return false;
}
catch (Exception e) { return false; }
}
}
}
** The if used in the try-catch statement could simply check if the return of the ExecuteScalar is null for non-existent DB and not-null if it exists.
you can get list of Database with below and check your db name:
USE master
GO
SELECT name, database_id, create_date
FROM sys.databases ;
GO
Related
I using this code to entering .
private void button1_Click(object sender, EventArgs e)
{
string Coonstring = "datasource=localhost;port=3306;username=root;password=****;Charset=utf8";
string cmd = "Insert into project.name_registry (name ) values('" + this.txt.Text + "');";
MySqlConnection connectionDatabase = new MySqlConnection(Coonstring);
MySqlCommand cmddata = new MySqlCommand(cmd, connectionDatabase);
MySqlDataReader myreader;
try
{
connectionDatabase.Open();
myreader = cmddata.ExecuteReader();
MessageBox.Show("Done");
while (myreader.Read())
{
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I need when press on this button check if the insert name found messagebox appear tell my the name exists and prevent the add. If not tell me the insert Done. How i can do this.
Regards
The best place to have this sort of check is in the database itself. Almost all databases can set a UNIQUE constraint on a field. If you set the name column in the name_registry to be unique, the DBMS won't let you add a second entry with the same name, and an exception will be thrown. This will usually be the best way.
If the DB isn't in your hands and you can't set the column to be unique, you can use the suggestion that #FrancisDucharme and others and query the DB for the given name, and only call the INSERT if it returns 0 results:
SELECT COUNT(*) FROM name_registry WHERE [name] = 'TheName'
Note, though that there's no need to call ExecuteReader, not for this single-result SELECT statement, nor for the INSERT statement above - you should call ExecuteScalar, which will return the single-value result without loading a full-scale DataReader that you don't really need.
And lastly, as an addition to the answer, I can't in good conscience let you go on without pointing you in the direction of at least one tutorial about using parameterized queries in ADO.NET, which not only help prevent SQL injection attacks, but also help clean up the code and make it more readable, in my opinion. There are many out there.
Firstly, As previously stated: You have MAJOR SQL Injections visible...
Secondly, You should be using params.
Third, If you
SELECT *
FROM [TABLE]
WHERE [ColumnName] = #Param
I'm currently polishing a C# app in relation with a SQL-Server base.
It's quite simple, you can add or remove entries from the SQL table via some fields from the application.
Question is :
On a Delete action, I've made this kind of query :
DELETE FROM table
WHERE ID = #ID
It deletes what I ask it to delete, BUT what if the query doesn't find anything in the DB ?
How can I detect that ?
Because in this case, the application deletes nothing, and no exception is raised.
To make it short, I'd just like to tell the user that there's nothing to delete in this case.
If you are using SqlCommand object, there is a method called ExecuteNonQuery. The method return how many rows are affected. So, zero means none.
private static void CreateCommand(string queryString,
string connectionString)
{
using (SqlConnection connection = new SqlConnection(
connectionString))
{
SqlCommand command = new SqlCommand(queryString, connection);
command.Connection.Open();
int rowsAffected = command.ExecuteNonQuery(); // <== this
}
}
delete from table where ID=#id
select ##rowcount
This will return how many rows there were actually deleted. You do not need the exists.
have a look at ##ROWCOUNT variable
http://technet.microsoft.com/en-us/library/ms187316.aspx
I'm using the MySql Connector .net, and I need to get the insert id generated by the last query. Now, I assume the return value of MySqlHelper.ExecuteNonQuery should be the last insert id, but it just returns 1.
The code I'm using is:
int insertID = MySqlHelper.ExecuteNonQuery(Global.ConnectionString,
"INSERT INTO test SET var = #var", paramArray);
However insertID is always 1. I tried creating a MySql connection and opening/closing manually which resulted in the same behaviour
Just use LastInsertedId field
MySqlCommand dbcmd = _conn.CreateCommand();
dbcmd.CommandText = sqlCommandString;
dbcmd.ExecuteNonQuery();
long imageId = dbcmd.LastInsertedId;
1 is the no of records effected by the query here only one row is inserted so 1 returns
for getting id of the inserted row you must use scope_identity() in sqlserver and LAST_INSERT_ID() in MySql
Try to use this query to get last inserted id -
SELECT LAST_INSERT_ID();
Then, run DbCommand.ExecuteReader method to get IDataReader -
command.CommandText = "SELECT LAST_INSERT_ID()";
IDataReader reader = command.ExecuteReader();
...and get information from the reader -
if (reader != null && reader.Read())
long id = reader.GetInt64(0);
...do not forget to close the reader;-)
I had the same problem, and after some testing, I found out that the problem seem to be the connection method; you are using a connection string.
This is of course to make use of the automatic connection pool reuse, but in this case it gave me trouble.
The final solution for me is to create a new connection, execute the insert query, and then execute the last_insert_id(). On the same connection.
Without using the same connection, last_insert_id() might return anything, I don't know why, but guess it looses track of things as it can be different connections.
Example:
MySqlConnection connection = new MySqlConnection(ConnectionString);
connection.Open();
int res = MySqlHelper.ExecuteNonQuery(
connection,
"INSERT INTO games (col1,col2) VALUES (1,2);");
object ores = MySqlHelper.ExecuteScalar(
connection,
"SELECT LAST_INSERT_ID();");
if (ores != null)
{
// Odd, I got ulong here.
ulong qkwl = (ulong)ores;
int Id = (int)qkwl;
}
I hope this helps someone!
I know this is an old post, but I have been facing the same issue as Snorvarg. Using MySqlHelper, and using a connection string instead of a Connection object (to allow MySqlHelper to use connection pooling), SELECT LAST_INSERT_ID() would often give me the ID of the previous query that was executed, or other times it would return zero. I would then have to call SELECT LAST_INSERT_ID() a second time to get the correct ID.
My solution was to encapsulate everything between the query that's being executed, and the calling of SELECT LAST_INSERT_ID() in a TransactionScope. This forces MySqlHelper to stick to one connection instead of opening two separate connections.
So:
string sql = "INSERT INTO games (col1,col2) VALUES (1,2);");
string connectionString = "some connection string";
using (TransactionScope scope = new TransactionScope)
{
int rowsAffected = MySqlHelper.ExecuteNonQuery(connectionString, sql);
object id = MySqlHelper.ExecuteScalar(connectionString, "SELECT LAST_INSERT_ID();");
scope.Complete();
}
try below working solution in repository .
string query = $"INSERT INTO `users`(`lastname`, `firstname`, `email`, `createdate`, `isdeleted`) " +
$"VALUES ('{userEntity.LastName}','{userEntity.FirstName}','{userEntity.Email}','{userEntity.CreateDate}',{userEntity.IsDeleted});" +
$"SELECT LAST_INSERT_ID();";
var res= _db.ExecuteScalar(query);
return (int)(UInt64)res;
I have a .NET Wndows application in C#. It's a simple Windows application that is using the MySql 5.1 database community edition. I've downloaded the MySql ODBC driver and have created a dsn to my database on my local machine. On my application, I can perform get type queries without problems, but when I execute a given insert statement (not that I've tried doing any others), I get the following error:
{"ERROR [HY001] [MySQL][ODBC 5.1 Driver][mysqld-5.0.27-community-nt]Memory allocation error"}
I'm running on a Windows XP machine. My machine has 1 GB of memory.
Anyone have any ideas? See code below
OdbcConnection MyConn = DBConnection.getDBConnection();
int result = -1;
try
{
MyConn.Open();
OdbcCommand myCmd = new OdbcCommand();
myCmd.Connection = MyConn;
myCmd.CommandType = CommandType.Text;
OdbcParameter userName = new OdbcParameter("#UserName", u.UserName);
OdbcParameter password = new OdbcParameter("#Password", u.Password);
OdbcParameter firstName = new OdbcParameter("#FirstName", u.FirstName);
OdbcParameter LastName = new OdbcParameter("#LastName", u.LastName);
OdbcParameter sex = new OdbcParameter("#sex", u.Sex);
myCmd.Parameters.Add(userName);
myCmd.Parameters.Add(password);
myCmd.Parameters.Add(firstName);
myCmd.Parameters.Add(LastName);
myCmd.Parameters.Add(sex);
myCmd.CommandText = mySqlQueries.insertChatUser;
result = myCmd.ExecuteNonQuery();
}
catch (Exception e)
{
//{"ERROR [HY001] [MySQL][ODBC 5.1 Driver][mysqld-5.0.27-community-nt]Memory
// allocation error"} EXCEPTION ALWAYS THROWN HERE
}
finally
{
try
{
if (MyConn != null) MyConn.Close();
}
finally { }
}
It was because some fields accept null, I had passed them as null where they should be passed as DBNull.Value. For all the fields which allow null should be checked for null and if found null, DBNull.Value should be passed.
Just for the sake of completeness, Chinjoo's SQL statement would likely be something like this:
mySqlQueries.insertChatUser = "insert into ChatUsers (UserName, Password, FirstName, LastName, sex) values (?,?,?,?,?);";
This is known as a parameterized insert where each question mark represents one of his parameters. In this simple example the order of the parameters in the parameter collection in code must match the order of the column names in the SQL statement.
While less elegant than using a function, the fix for his null problem would look something like this for one of his parameters:
OdbcParameter LastName = new OdbcParameter("#LastName", u.LastName);
is replaced with
// if the value is "null" return DBNull, else just the value
OdbcParameter LastName = new OdbcParameter("#LastName",
(u.LastName == null) ? System.DBNull.Value : (object)u.LastName);
At least in my code (which is slightly different) the inner cast to type object is required since otherwise the compiler isn't sure what type the ?: operator should return.
Hope this helps anyone who is relatively new to parameterization, etc.
No criticism of Chinjoo implied at all--his posting helped me out! Just thought I'd share for the less-experienced. I'm by no means expert so take everything I say with a grain of salt.
This exception also can be raised if you try to insert invalid chars in a VARCHAR field. In example, if the string is generated by a UNIX machine and has end of line characters '\n'. You can just replace that problematic characters to Windows style, or viceversa, or just delete it if you don't want to store end of lines.
You can check the strings, and if any of them has end of line characters, try to repeat the insert deleting them. If it works, the problem are these characters.
What's the best way to check if a table exists in a Sql database in a database independant way?
I came up with:
bool exists;
const string sqlStatement = #"SELECT COUNT(*) FROM my_table";
try
{
using (OdbcCommand cmd = new OdbcCommand(sqlStatement, myOdbcConnection))
{
cmd.ExecuteScalar();
exists = true;
}
}
catch
{
exists = false;
}
Is there a better way to do this? This method will not work when the connection to the database fails. I've found ways for Sybase, SQL server, Oracle but nothing that works for all databases.
bool exists;
try
{
// ANSI SQL way. Works in PostgreSQL, MSSQL, MySQL.
var cmd = new OdbcCommand(
"select case when exists((select * from information_schema.tables where table_name = '" + tableName + "')) then 1 else 0 end");
exists = (int)cmd.ExecuteScalar() == 1;
}
catch
{
try
{
// Other RDBMS. Graceful degradation
exists = true;
var cmdOthers = new OdbcCommand("select 1 from " + tableName + " where 1 = 0");
cmdOthers.ExecuteNonQuery();
}
catch
{
exists = false;
}
}
If you're trying for database independence you will have to assume a minimum standard. IIRC The ANSI INFORMATION_SCHEMA views are required for ODBC conformance, so you could query against them like:
select count (*)
from information_schema.tables
where table_name = 'foobar'
Given that you are using ODBC, you can also use various ODBC API calls to retrieve this metadata as well.
Bear in mind that portability equates to write-once test anywhere so you are still going to have to test the application on every platform you intend to support. This means that you are inherently limited to a finite number of possible database platforms as you only have so much resource for testing.
The upshot is that you need to find a lowest common denominator for your application (which is quite a lot harder than it looks for SQL) or build a platform-dependent section where the non-portable functions can be plugged in on a per-platform basis.
I don't think that there exists one generic way that works for all Databases, since this is something very specific that depends on how the DB is built.
But, why do you want to do this using a specific query ?
Can't you abstract the implementation away from what you want to do ?
I mean: why not create a generic interface, which has among others, a method called 'TableExists( string tablename )' for instance.
Then, for each DBMS that you want to support , you create a class which implements this interface, and in the TableExists method, you write specific logic for this DBMS.
The SQLServer implementation will then contain a query which queries sysobjects.
In your application, you can have a factory class which creates the correct implementation for a given context, and then you just call the TableExists method.
For instance:
IMyInterface foo = MyFactory.CreateMyInterface (SupportedDbms.SqlServer);
if( foo.TableExists ("mytable") )
...
I think this is how I should do it.
I fully support Frederik Gheysels answer. If you have to support multiple database systems, you should implement your code against an abstract interface with specific implementations per database system. There are many more examples of incompatible syntax than just checking for an existing table (e.g.: limiting the query to a certain number of rows).
But if you really have to perform the check using the exception handling from your example, you should use the following query that is more efficient than a COUNT(*) because the database has no actual selection work to do:
SELECT 1 FROM my_table WHERE 1=2
I would avoid executing the select count(x) from xxxxxx as the DBMS will actually go ahead and do it which may take some time for a large table.
Instead just prepare a select * from mysterytable query. The prepare will fail if mysterytable does not exist. There is no need to actually execute the prepared statement.
The following works well for me...
private bool TableExists(SqlConnection conn, string database, string name)
{
string strCmd = null;
SqlCommand sqlCmd = null;
try
{
strCmd = "select case when exists((select '['+SCHEMA_NAME(schema_id)+'].['+name+']' As name FROM [" + database + "].sys.tables WHERE name = '" + name + "')) then 1 else 0 end";
sqlCmd = new SqlCommand(strCmd, conn);
return (int)sqlCmd.ExecuteScalar() == 1;
}
catch { return false; }
}
In current project on my job I need to write 'data agent' which would support a lot of database types.
So I decided to do next: write a base class with the base (database independent) functionality using virtual methods and override in subclasses all database-specific moments
Very Simple
use YOUR_DATABASE --OPTIONAL
SELECT count(*) as Exist from INFORMATION_SCHEMA.TABLES where table_name = 'YOUR_TABLE_NAME'
If the answer is 1, There is a table.
If the answer is 0, There is no table.
If you want to avoid try-catch solutions, I'm suggesting this method, using sys.tables
private bool IsTableExisting(string table)
{
string command = $"select * from sys.tables";
using (SqlConnection con = new SqlConnection(Constr))
using (SqlCommand com = new SqlCommand(command, con))
{
SqlDataReader reader = com.ExecuteReader();
while (reader.Read())
{
if (reader.GetString(0).ToLower() == table.ToLower())
return true;
}
reader.Close();
}
return false;
}