My table structure is as follows:
Session
--------------
SessionID (PK)
RoomID
SessionDate
SessionTimeStart
SessionTimeEnd
I have a following query which will always return one row and display in DGV. I use DataAdapter for connection:
DataTable queryResult = new DataTable();
string ConnStr = "Data Source=DUZY;Initial Catalog=AutoRegSQL;Integrated Security=True";
SqlConnection MyConn = new SqlConnection(ConnStr);
MyConn.Open();
//SQL query that returns todays sessions for the given roomID
string query = #"SELECT SessionID, RoomID, SessionDate, SessionTimeStart, SessionTimeEnd" +
" FROM [Session] " +
" WHERE RoomID = #RoomID " +
" AND SessionDate = cast(getdate() as date) ";
SqlCommand command = new SqlCommand(query, MyConn);
command.Parameters.Add("RoomID", SqlDbType.Char).Value = RoomID;
SqlDataAdapter adapter = new SqlDataAdapter(command);
adapter.Fill(queryResult);
I would like to save the query result into multiple strings representing table columns, i.e.
SessionIDstring = query result for SessionID column
RoomIDstring = query result for RoomID column
and so on...
Is it possible to achieve it using one query, or do I have to create 5 queries for each column?
Something similar to this, perhaps, using ADO.NET?
//SQL query that returns todays sessions for the given roomID
string query = #"SELECT SessionID, RoomID, SessionDate, SessionTimeStart, SessionTimeEnd" +
" FROM [Session] " +
" WHERE RoomID = #RoomID " +
" AND SessionDate = cast(getdate() as date) ";
using (var connection = new SqlConnection(ConnStr))
using (var command = new SqlCommand(query, connection))
{
command.Parameters.Add("RoomID", SqlDbType.Char).Value = RoomID;
try
{
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
if (reader.Read())
{
// Note that reader[x] has the equivalent type to the type
// of the returned column, converted using
// http://msdn.microsoft.com/en-us/library/cc716729.aspx
// .ToString() if the item isn't null is always ok
string SessionIDstring = reader[0].ToString(); // it should be an int
// reading it twice is ok
int RoomID = (int)reader[1]; // it should be an int
string RoomIDstring = reader[1].ToString(); // it should be an int
if (reader.Read())
{
throw new Exception("Too many rows");
}
}
else
{
throw new Exception("No rows");
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
This code was adapted from MSDN ADO.NET Code Examples. I added some usings and made it single row. I don't even want to know why MSDN examples don't go the full length with using.
Note that SqlDataAdapter are built to recover multiple rows/big data and put them in a DataSet. You can use them for single row data, but it's much easier to simply use a SqlDataReader if you only want to fill some variables.
declare #col1 int
declare #col2 varchar(42)
select #col1 = col1
, #col2 = col2
, ....
You could create a class like so...
public class SessionDto
{
public string SessionID {get; set;}
public string RoomID {get; set;}
public string SessionDate {get; set;}
public string SessionTimeStart {get; set;}
public string SessionTimeEnd {get; set;}
}
And then have a method that takes a Room ID and builds your session object
public SessionDto GetSessionData(int roomId)
{
using (var cnn = new SqlConnection(ConnStr))
{
SessionDto sessionDto;
string query = #"SELECT SessionID, RoomID, SessionDate, SessionTimeStart, SessionTimeEnd" +
" FROM [Session] " +
" WHERE RoomID = #RoomID " +
" AND SessionDate = cast(getdate() as date) ";
cnn.Open();
using (var cmd = new SqlCommand(query,cnn))
{
cmd.Parameters.Add("#RoomID", SqlDbType.Char).Value = roomId;
using (var rdr = cmd.ExecuteReader())
{
if (rdr.HasRows)
{
while (rdr.Read())
{
sessionDto = new sessionDto{
SessionID = rdr.GetString(0),
RoomID = rdr.GetString(1),
SessionDate = rdr.GetString(2),
SessionTimeStart = rdr.GetString(3),
SessionTimeEnd = rdr.GetString(4)
};
}
}
}
}
}
return sessionDto;
}
A lot of this is hand typed as I havent got access to VS right now,
but you should get it to work.
Also, I have used rdr.GetString(), there are other methods for GetType().
Related
This is my code in C#. I am just trying to add data to my table in the database. However, I have been having this issue for only ages. It says:
invalid column name.
Fotograf database is the only database I have and table ODEV1 is the only table I created. When I edit data through SQL Server there is not an issue, but when I try it by using Visual Studio C# I have issues.
Any help appreciated thank you!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Data.SqlClient;
namespace SQL_ORNEK2
{
class Program
{
static void Main(string[] args)
{
SqlConnection baglanti = new SqlConnection();
baglanti.ConnectionString = "Server=LAPTOP-K3JLTUR0; database=Fotograf; integrated security=True";
SqlCommand komut = new SqlCommand();
komut.Connection = baglanti;
string name;
name = Console.ReadLine().ToString();
string surname;
surname = Console.ReadLine().ToString();
int age;
age = Convert.ToInt32(Console.ReadLine());
string job;
job = Console.ReadLine().ToString();
komut.CommandText = "INSERT INTO dbo.ODEV1 VALUES('name', 'surname', age, 'job')";
baglanti.Open();
int sonuc = komut.ExecuteNonQuery();
Console.WriteLine(sonuc);
Console.ReadKey();
baglanti.Close();
}
}
}
Your insert statement is incorrect. You're using the list of columns in place of the values to insert. It should look something like this:
insert into dbo.ODEV1 (name, surname, age, job) values ('Harold', 'Green', 25, 'nerd')
To insert the actual data from the variables you read from user input, you'll want to use SQL parameters:
komut.Parameters.AddWithValue("#name", name);
komut.Parameters.AddWithValue("#surname", surname);
komut.Parameters.AddWithValue("#age", age);
komut.Parameters.AddWithValue("#job", job);
komut.CommandText = "insert into dbo.ODEV1 (name, surname, age, job) values (#name, #surname, #age, #job)";
If you use SSMS (SQL-Server Management Studio which is free) to create your INSERT INTO statement by right clicking the desired table, select "script table as", select "INSERT To" to a new query window we get this (using a table named Customers).
INSERT INTO [dbo].[Customer]
([FirstName]
,[LastName]
,[Address]
,[City]
,[State]
,[ZipCode]
,[AccountNumber]
,[JoinDate])
VALUES
(<FirstName, nvarchar(max),>
,<LastName, nvarchar(max),>
,<Address, nvarchar(max),>
,<City, nvarchar(max),>
,<State, nvarchar(max),>
,<ZipCode, nvarchar(max),>
,<AccountNumber, nvarchar(max),>
,<JoinDate, datetime2(7),>)
Now change the VALUES section by using a DECLARE for each value.
DECLARE #FirstName nvarchar(max)
DECLARE #LastName nvarchar(max)
DECLARE #Address nvarchar(max)
DECLARE #City nvarchar(max)
DECLARE #State nvarchar(max)
DECLARE #ZipCode nvarchar(max)
INSERT INTO Customer (FirstName,LastName,[Address],City,[State],ZipCode) VALUES (#FirstName,#LastName,#Address,#City,#State,#ZipCode)
Next, create a class rather than placing data operations into Program.cs with a method specific to adding a new record (the following still uses Customers table).
Full source where the following code comes from.
An alternate to cmd.Parameters.AddWithValue is cmd.Parameters.Add which provides fine tuning the type of the parameter.
The alternate to getting the new primary key if needed is to add a semi-colon to the end of the INSERT INTO and adding SELECT CAST(scope_identity() AS int); then use Convert.ToInt32(cmd.ExecuteScalar()) to get the new key.
So after testing with SSMS simply paste the query into a string variable and if this does not work there is something else going on.
public bool AddCustomer(string FirstName, string LastName, string Address, string City, string State, string ZipCode, ref int NewPrimaryKeyValue)
{
bool success = false;
using (var cn = new SqlConnection { ConnectionString = ConnectionString })
{
using (var cmd = new SqlCommand { Connection = cn })
{
cmd.CommandText =
"INSERT INTO Customer (FirstName,LastName,[Address],City,[State],ZipCode) " +
"VALUES (#FirstName,#LastName,#Address,#City,#State,#ZipCode)";
try
{
cmd.Parameters.AddWithValue("#FirstName", FirstName);
cmd.Parameters.AddWithValue("#LastName", LastName);
cmd.Parameters.AddWithValue("#Address", Address);
cmd.Parameters.AddWithValue("#City", City);
cmd.Parameters.AddWithValue("#State", State);
cmd.Parameters.AddWithValue("#ZipCode", ZipCode);
cn.Open();
int result = cmd.ExecuteNonQuery();
if (result == 1)
{
cmd.CommandText = "Select ##Identity";
NewPrimaryKeyValue = Convert.ToInt32(cmd.ExecuteScalar());
success = true;
}
}
catch (Exception ex)
{
HasErrors = true;
ExceptionMessage = ex.Message;
NewPrimaryKeyValue = -1;
success = false;
}
}
}
return success;
}
Calling the above method.
You can also validate column names using the following (still keeping with Customer table)
SELECT ORDINAL_POSITION,
COLUMN_NAME,
DATA_TYPE
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Customer'
AND TABLE_SCHEMA = 'dbo';
Results
1,id,int
2,FirstName,nvarchar
3,LastName,nvarchar
4,Address,nvarchar
5,City,nvarchar
6,State,nvarchar
7,ZipCode,nvarchar
8,AccountNumber,nvarchar
9,JoinDate,datetime2
Edit
Another option is to create a class which represents data to be inserted e.g.
public class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public string AccountNumber { get; set; }
public DateTime? JoinDate { get; set; }
}
Then here we use the values passed. Note, in this version cmd.Parameters.AddWithValue is replaced with cmd.Parameters.Add and the query to get the new primary key is appended after the INSERT INTO separated by a semi-colon.
To call create an instance of the Customer class, populate properties and call the method.
public bool AddCustomer(Customer customer)
{
bool success = false;
using (var cn = new SqlConnection { ConnectionString = ConnectionString })
{
using (var cmd = new SqlCommand { Connection = cn })
{
cmd.CommandText =
"INSERT INTO Customer (FirstName,LastName,[Address],City,[State],ZipCode) " + // insert
"VALUES (#FirstName,#LastName,#Address,#City,#State,#ZipCode);" + // insert
"SELECT CAST(scope_identity() AS int);"; // get new primary key
try
{
cmd.Parameters.Add(new SqlParameter("#FirstName", SqlDbType.NVarChar))
.Value = customer.FirstName;
cmd.Parameters.Add(new SqlParameter("#LastName", SqlDbType.NVarChar))
.Value = customer.LastName;
cmd.Parameters.Add(new SqlParameter("#Address", SqlDbType.NVarChar))
.Value = customer.Address;
cmd.Parameters.Add(new SqlParameter("#City", SqlDbType.NVarChar))
.Value = customer.City;
cmd.Parameters.Add(new SqlParameter("#State", SqlDbType.NVarChar))
.Value = customer.State;
cmd.Parameters.Add(new SqlParameter("#ZipCode", SqlDbType.NVarChar))
.Value = customer.ZipCode;
cn.Open();
customer.Id = Convert.ToInt32(cmd.ExecuteScalar());
success = true;
}
catch (Exception ex)
{
HasErrors = true;
ExceptionMessage = ex.Message;
customer.Id = -1;
success = false;
}
}
}
return success;
}
I want to retrive data from two differentables in my mysql data base so i created one connection and two readers, The second reader is not returning any results but the first reader is.
public List<BlogContentItemClass> BCITLIST = new List<BlogContentItemClass>();
// GET: api/BlogContents
[HttpGet]
public List<BlogContentItemClass> Get(string id)
{
string sqlstring = "server=; port= ; user id =;Password=;Database=;";
MySqlConnection conn = new MySqlConnection(sqlstring);
try
{
conn.Open();
}
catch (MySqlException ex)
{
throw ex;
}
string Query = "SELECT * FROM test.blogtable where `id` = '" + id + "' ";
MySqlCommand cmd = new MySqlCommand(Query, conn);
MySqlDataReader MSQLRD = cmd.ExecuteReader();
BlogContentItemClass BCIT = new BlogContentItemClass();
Label BLOGID = new Label();
if (MSQLRD.HasRows)
{
while (MSQLRD.Read())
{
string TC = (MSQLRD["Topic"].ToString());
string CT = (MSQLRD["Category"].ToString());
string SM = (MSQLRD["Summary"].ToString());
string BID = (MSQLRD["id"].ToString());
BCIT.TopicSaved1 = TC;
BCIT.CategoriesSaved1 = CT;
BCIT.SummarySaved1 = SM;
BLOGID.Text = BID;
BCIT.TotalBodyStackLayout1.Add("Hello");
}
}
BCITLIST.Add(BCIT);
MSQLRD.Close();
string Query1 = "SELECT * FROM test.blogbodytable where `BlogID` = '" + BLOGID.Text + "' ";
MySqlCommand cmd1 = new MySqlCommand(Query1, conn);
MySqlDataReader MSQLRD1 = cmd1.ExecuteReader();
if (MSQLRD1.HasRows)
{
while (MSQLRD1.Read())
{
string BLOGBODY ;
BLOGBODY = (MSQLRD1["BlogBody"].ToString());
BCIT.TotalBodyStackLayout1.Add(BLOGBODY);
}
}
BCITLIST.Add(BCIT);
conn.Close();
return BCITLIST;
}
from my code the line BCIT.TotalBodyStackLayout1.Add("Hello"); in the first reader does add "hello" to the BCIT.TotalBodyStacklayout1, but the line BCIT.TotalBodyStackLayout1.Add( BLOGBODY); does not work, what am i doing wrong?
Can you be more specific what you mean by 'BCIT.TotalBodyStackLayout1.Add(BLOGBODY);' does not work. Are you getting any exception? or if BLOGBODY coming empty? There are few primitive troubleshooting steps you can perform to nail-down the issue
confirm what BLOGID.Text you are getting from your previous query and corresponding data is available in test.blogbodytable for that id.
if (MSQLRD1.HasRows) is resolving to true
Were you able to get inside while (MSQLRD1.Read())
Hello guys I am trying to do some stuff while reading. What I am trying to do is edit row which was just read. But I get error. Maybe u have some suggestions how should I fix it, to make it work without quitting the data reader. P.S: Ignore that, that queries are open for SQL injections .
string select = "Select * FROM ivykiai WHERE `Ivikio diena` MOD Periodiskumas_d = 0 AND `Ivikio diena` > 0 AND `Ivikio diena` < `Dif dien`";
MySqlCommand command = new MySqlCommand(select, cnn);
MySqlDataReader reader = command.ExecuteReader();
while (reader.Read())
{
db1 = (now - Convert.ToDateTime(reader["Nuo"])).TotalDays;
MessageBox.Show(db1.ToString());
db1 = db1 - Convert.ToInt32(reader["Ivikio diena"]);
MessageBox.Show(db1.ToString());
b = Convert.ToInt32(db1) / Convert.ToInt32(reader["Periodiskumas_d"]);
MessageBox.Show(b.ToString());
a =+ Convert.ToInt32(reader["Suma"]);
MessageBox.Show(a.ToString());
a = a * b;
MessageBox.Show(a.ToString());
string prideti = "Update Lesos Set Grynieji=Grynieji + '"+ a +"'";
MySqlCommand prideti_cmd = new MySqlCommand(prideti, cnn);
string p = prideti_cmd.ExecuteNonQuery().ToString();
string update = "UPDATE Ivikiai Set `Ivykio diena`+= '" + db1 + "'";
MySqlCommand update_cmd = new MySqlCommand(update, cnn);
string u = update_cmd.ExecuteNonQuery().ToString();
}
reader.Close();
cnn.Close();
You can't execute prideti_cmd and update_cmd using the same connection inside the while (reader.Read()) block and reader is still open, however you can do that outside the while (reader.Read()) block and after closing reader. I would suggest creating the following class
public class MyClass
{
public DateTime Nuo { get; set; }
public int IvikioDiena { get; set; }
public int Periodiskumas_d { get; set; }
public int Suma { get; set; }
}
and change your code as below
string select = "Select * FROM ivykiai WHERE `Ivikio diena` MOD Periodiskumas_d = 0 AND `Ivikio diena` > 0 AND `Ivikio diena` < `Dif dien`";
using (MySqlCommand command = new MySqlCommand(select, cnn))
{
// execute the select query and store the results to list variable
List<MyClass> list = new List<MyClass>();
using (MySqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
MyClass record = new MyClass();
record.Nuo = Convert.ToDateTime(reader["Nuo"]);
record.IvikioDiena = Convert.ToInt32(reader["Ivikio diena"]);
record.Periodiskumas_d = Convert.ToInt32(reader["Periodiskumas_d"]);
record.Suma = Convert.ToInt32(reader["Suma"]);
list.Add(record);
}
}
// enumerate list and execute both the update queries
foreach (var record in list)
{
db1 = (now - record.Nuo).TotalDays;
MessageBox.Show(db1.ToString());
db1 = db1 - record.IvikioDiena;
MessageBox.Show(db1.ToString());
b = Convert.ToInt32(db1) / record.Periodiskumas_d;
MessageBox.Show(b.ToString());
a =+ record.Suma;
MessageBox.Show(a.ToString());
a = a * b;
MessageBox.Show(a.ToString());
string prideti = "Update Lesos Set Grynieji=Grynieji + '"+ a +"'";
MySqlCommand prideti_cmd = new MySqlCommand(prideti, cnn);
string p = prideti_cmd.ExecuteNonQuery().ToString();
string update = "UPDATE Ivikiai Set `Ivykio diena`+= '" + db1 + "'";
MySqlCommand update_cmd = new MySqlCommand(update, cnn);
string u = update_cmd.ExecuteNonQuery().ToString();
}
}
Generally you can ever only have one active command - SQL Server MARS being a little exceptiohn.
So, you can not use a connection WHILE IT HAS AN OPEN READER. Your first need to finish reading, then can update- or use anothe connection, which will get you into transaction isolation troubles.
Try this:
using (MySqlConnection cnn = new MySqlConnection(dbConnectionString))
{
cnn.Open();
MySqlCommand command = new MySqlCommand(select, cnn);
using (MySqlDataReader reader = command.ExecuteReader())
{
db1 = (now - Convert.ToDateTime(reader["Nuo"])).TotalDays;
MessageBox.Show(db1.ToString());
db1 = db1 - Convert.ToInt32(reader["Ivikio diena"]);
MessageBox.Show(db1.ToString());
b = Convert.ToInt32(db1) / Convert.ToInt32(reader["Periodiskumas_d"]);
MessageBox.Show(b.ToString());
a = +Convert.ToInt32(reader["Suma"]);
MessageBox.Show(a.ToString());
a = a * b;
MessageBox.Show(a.ToString());
}
string prideti = "Update Lesos Set Grynieji=Grynieji + '" + a + "'";
MySqlCommand prideti_cmd = new MySqlCommand(prideti, cnn);
string p = prideti_cmd.ExecuteNonQuery().ToString();
string update = "UPDATE Ivikiai Set `Ivykio diena`+= '" + db1 + "'";
MySqlCommand update_cmd = new MySqlCommand(update, cnn);
string u = update_cmd.ExecuteNonQuery().ToString();
}
All of the variables needed for the ExecuteNonQuery() are set when the data is read so you can use them outside the MySqlDataReader.ExecuteReader() function.
I am semi-new to C# but in particular using Sqlite within C#, currently I have a SQlite DB setup fine in terms of it connects with the application well I am running windows form application and I have bound a table within the database to a datagrid view.
This is all fine I have a function setup to run queries where i pass the SQL statement as a string to the function and it runs it as a query.
I was wandering how I do I get a result back from the query I know obviosuly it will be somthing like
private string QueryResult(string query){
connect
run query
read query
return result
}
All th examples I have seen use Sqlreader but I can't seem to get it work, I am really used to using PHP with SQL and that seems so much simpler than using it in C# can someone explain or point out somewhere I might be able to find a tutuorial or function that you can run any query in by passing it as a string and getting the result returned pretty simply? The results I need wont be arrays or huge things I am only looking to return 1 word strings or numbers at a time so I don't need anything complicated.
Please help me out I spent about 4 hours reading about this stuff last night and didn't seem to get anywhere.
Try this, maybe it will help you:
public string QueryResult(string query)
{
string result = "";
SQLiteConnection sqlite = new SQLiteConnection("Data Source=/path/to/file.db");
try
{
sqlite.Open(); //Initiate connection to the db
SQLiteCommand cmd = sqlite.CreateCommand();
cmd.CommandText = query; //set the passed query
result = cmd.ExecuteScalar().ToString();
}
finally
{
sqlite.Close();
}
return result;
}
Heres a method that I have Used....
First off, build a class to represent a Table in your DataBase :-
public class Contact
{
public int ContactID { get; set; }
public string Surname { get; set; }
public string Forename { get; set; }
public string MobileNumber { get; set; }
public string EmailAddress { get; set; }
public string Information { get; set; }
}
Then I load this Data into an IEnumerable List :-
public List<Contact> GetContacts()
{
DataTable dt = new DataTable();
OleDbCommand cmd = new OleDbCommand("SELECT * FROM [Contacts]", Connection);
Adapter.SelectCommand = cmd;
Connection.Open();
Adapter.SelectCommand.ExecuteNonQuery();
Adapter.Fill(dt);
Connection.Close();
var Contacts = (from row in dt.AsEnumerable()
select new Contact
{
ContactID = row.Field<int>("ContactID"),
Surname = row.Field<string>("Surname"),
Forename = row.Field<string>("Forename"),
MobileNumber = row.Field<string>("MobileNumber"),
EmailAddress = row.Field<string>("EmailAddress"),
Information = row.Field<string>("Information")
}).ToList();
return Contacts;
}
In My application I create an Instance of this Object :-
public List<Contact> contactData;
contactData = dc.GetContacts();
I now have the power to manipulate the data using LINQ :-
var Query = ConactData.Where(item=> item.ContactID == 10)
.Select(item=> item.Surname).toString();
You can use LINQ to query your Data and store it as Lists, Strings etc etc.
Hope This Helps.
Usually, I do something like:
string CONNECTION_STRING = "Persist Security Info=False; Integrated Security = SSPI; Initial Catalog=DATABASENAME;Data Source=SERVERIP";
string query = "IF OBJECT_ID('TABLE_NAME') IS NOT NULL SELECT * FROM TABLE_NAME";
using (SqlConnection Connection = new SqlConnection(CONNECTION_STRING))
{
using (SqlCommand sqlCommand = new SqlCommand(query, ConnectionString))
{
try
{
Connection.Open();
SqlDataReader queryCommandReader = sqlCommand.ExecuteReader();
DataTable dataTable = new DataTable();
dataTable.Load(queryCommandReader);
if (dataTable != null)
{
if (dataTable.Rows != null)
{
if (dataTable.Rows.Count > 0)
{
String rowText = "";
rowText += dataTable.Rows[ROW_NUM] [COLUMN_NAME];
}
}
}
}
catch (Exception)
{
...
}
finally
{
...
}
//in normal logic
SELECT (SELECT SUM(column_name) FROM table_name WHERE condition) - (SELECT SUM(column_name) FROM table_name WHERE condition)
//actual coding example
public void total_due()
{
string query = "select (select sum(amount) from table_name where id>0 and amount>paid and [order no] like '" + textbox1.Text + "%' and [name] like '" + textbox2.Text + "%' and [date] like '" + textbox3.Text + "%' ) - (select sum(paid) from table_name where id>0 and amount>paid and [order no] like '" + textbox1.Text + "%' and [name] like '" + textbox2.Text + "%' and [date] like '" + textbox3.Text + "%' )";
SqlConnection con = new SqlConnection("server=server_name;Database=database_name;UID=sa;Password=password;");
con.Open();
SqlCommand cmd = new SqlCommand(query,con);
due.Text = cmd.ExecuteScalar().ToString();
con.Close();
}
I need a way to check if a table exist in my database from my C# class, and if that table got the rows needed.
If it doesn't exist or some of the rows are missing, I need to add those.
I've used this method but don't know how to get the missing functions in there.
( Check if a SQL table exists )
I'm working with SQL Server and C#
I'm going to attach a script here that will dump all the objects and columns for the objects in a TempTable. I run the same script on the DB that I'm comparing with, and check which objects doesn't exists, and which columns in which tables does not exist, and which columns have changed. I've used a Delphi app very long ago then to "upgrade" my DB's
I run this code on the MASTER database.
If Exists(Select 1 from sysobjects where name = 'CheckTables')
Drop Table CheckTables
GO
Select o.id oid, o.name oname, c.colid cid, c.name cname, t.name ctype, c.xusertype, c.[length] tlength, c.prec cprec, c.scale cscale, isnullable
into CheckTables
from sysobjects o
inner join syscolumns c on c.id = o.id
inner join systypes t on t.xusertype = c.xusertype
where o.name not like '%dt_%' and o.category <> 2 and o.type = 'U'
order by o.id, c.colid
Delete CheckTables where oname = 'CheckTables'
Then I bcp the data into a flat file
When I ran my upgrade, I create a table on the Upgrade DB with the same structure, and bcp the data of the Master DB in there.
Then I used this script then in my Delphi App to check what changed.
Select oname, cname, ctype, IsNull(tlength, 0), IsNull(cprec, 0), IsNull(cscale, 0), ctype, isnullable from CheckTables hr
where cname not in (Select name from syscolumns where id = object_id(oname)
and length = hr.tlength
and xusertype = hr.xusertype
and isnullable = hr.isnullable)
order by oname
This should get you going.
If you need more information on the C# part of it, I can give you some code.
Here is C# code to get you going. There is some stuff that you will have to add yourself, but if you strugle, let me know.
private void UpgradeDB()
{
SqlConnection conn = new SqlConnection("Some Connection String");
SqlCommand cmd = new SqlCommand();
cmd.Connection = conn;
conn.Open();
cmd.CommandText = "If 1 = (Select 1 from sysobjects where id = object_id('CheckTables'))\r\n" +
" Drop Table CheckTables\r\n" +
"Create Table CheckTables\r\n" +
"(oid int,\r\n" +
"oname varchar(50),\r\n" +
"colid int,\r\n" +
"cname varchar(50),\r\n" +
"ctype varchar(50),\r\n" +
"cxtype int,\r\n" +
"tlength int,\r\n" +
"cPrec int,\r\n" +
"cScale int,\r\n" +
"isnullable int";
cmd.ExecuteNonQuery();
//BCP your data from MASTER TABLE into the CheckTables of the UpgradeDB
cmd.CommandText = "Select oname, cname, ctype, IsNull(tlength, 0), IsNull(cprec, 0), IsNull(cscale, 0), isnullable from CheckTables hr\r\n" +
"where cname not in (Select name from syscolumns where id = object_id(oname)\r\n" +
"and length = hr.tlength\r\n" +
"and xusertype = hr.xusertype\r\n" +
"and isnullable = hr.isnullable)\r\n" +
"order by oname";
SqlDataReader read = cmd.ExecuteReader();
string LastTable = "";
bool TableExists = false;
bool ColumnExists = false;
while(read.Read())
{
if(LastTable != read[0].ToString())
{
LastTable = read[0].ToString();
TableExists = false;
if (!CheckIfTableExist(LastTable))
TableExists = CreateTable(LastTable);
else
TableExists = true;
}
if (TableExists)
{
if (!CheckIfColumnExists(read[0].ToString(), read[1].ToString()))
{
CreateColumn(read[0].ToString(), read[1].ToString(), read[2].ToString(),
Convert.ToInt32(read[3].ToString()), Convert.ToInt32(read[4].ToString()),
Convert.ToInt32(read[5].ToString()), Convert.ToBoolean(read[6].ToString()));
ColumnExists = false; //You don't want to alter the column if you just created it
}
else
ColumnExists = true;
if(ColumnExists)
{
AlterColumn(read[0].ToString(), read[1].ToString(), read[2].ToString(),
Convert.ToInt32(read[3].ToString()), Convert.ToInt32(read[4].ToString()),
Convert.ToInt32(read[5].ToString()), Convert.ToBoolean(read[6].ToString()));
}
}
}
read.Close();
read.Dispose();
conn.Close();
cmd.Dispose();
conn.Dispose();
}
private bool CheckIfTableExist(string TableName)
{
SqlConnection conn = new SqlConnection("Connection String");
SqlCommand cmd = new SqlCommand();
conn.Open();
cmd.Connection = conn;
cmd.CommandText = "Select IsNull(object_id('" + TableName + "'), 0)";
Int64 check = Convert.ToInt64(cmd.ExecuteScalar());
conn.Close();
cmd.Dispose();
conn.Dispose();
return check != 0;
}
private bool CreateTable(string TableName)
{
try
{
//Write your code here to create your table
return true;
}
catch
{
return false;
}
}
private bool CheckIfColumnExists(string TableName, string ColName)
{
SqlConnection conn = new SqlConnection("Connection String");
SqlCommand cmd = new SqlCommand();
conn.Open();
cmd.Connection = conn;
cmd.CommandText = "Select IsNull(id, 0) from syscolumns where id = object_id('" + TableName + "') and name = '" + ColName + "'";
Int64 check = Convert.ToInt64(cmd.ExecuteScalar());
conn.Close();
cmd.Dispose();
conn.Dispose();
return check != 0;
}
private void CreateColumn(string TableName, string ColName, string ColType, int Length, int Precision, int Scale, bool Nullable)
{
//Write your code here to create your column
}
private void AlterColumn(string TableName, string ColName, string ColType, int Length, int Precision, int Scale, bool Nullable)
{
//Write your code here to alter your column
}