Update the datatable without using DataAdapter.Fill 2 times - c#

I am writing a program to manage a office. (Getting rid of Excels XD).
I have a DAL class with the following variables:
private MySqlConnection connection;
private DataSet ds;
private Hashtable adapters;
There is this method:
public bool AddTable(string tableName, string sqlStat)
{
if (!ds.Tables.Contains(tableName))
{
MySqlDataAdapter adapter = new MySqlDataAdapter(sqlStat, connection);
MySqlCommandBuilder builder = new MySqlCommandBuilder(adapter);
adapter.InsertCommand = builder.GetInsertCommand();
adapter.UpdateCommand = builder.GetUpdateCommand();
adapter.DeleteCommand = builder.GetDeleteCommand();
adapter.Fill(ds, tableName);
adapters.Add(tableName, adapter);
return true;
}
return false;
}
The program will be connected to a server with MySQL database.
I need to make sure that when one client changes something in the database another client will see the new data, but this is not happening.

You need to read up on optimistic concurrency, which helps solve the problem of multiple users reading and updating the same data at the same time.
I suggest you start here:
http://msdn.microsoft.com/en-us/library/aa0416cz%28v=vs.110%29.aspx
http://www.codeproject.com/Articles/114262/6-ways-of-doing-locking-in-NET-Pessimistic-and-opt

Related

How to make a DataReader for global use

I have this code in my SQL Connect class.
public class SqlConnect
{
public string connectionString = ConfigurationManager.ConnectionStrings["cn"].ConnectionString;
private SqlConnection con;
public SqlCommand cmd;
private SqlDataAdapter sda;
private DataTable dt;
private SqlDataReader sdr;
public SqlConnect()
{
con = new SqlConnection(connectionString);
con.Open();
}
public void SqlQuery(string queryTxt)
{
cmd = new SqlCommand(queryTxt, con);
}
public DataTable QueryEx()
{
sda = new SqlDataAdapter(cmd);
dt = new DataTable();
sda.Fill(dt);
con.Close();
return dt;
}
public void NonQueryEx()
{
cmd.ExecuteNonQuery();
con.Close();
}
public void Reader()
{
sdr = cmd.ExecuteReader();
while(sdr.Read())
{
for (int i = 0; i < sdr.FieldCount; i++) ;
}
return;
}
Now, in my button I have this code. I'm having error saying cannot convert from Void to Object.
con = new SqlConnect();
con.SqlQuery("Select Department from Salary");
cboDept.Items.Add(con.Reader());
My question is how can I make this run? when I use the public datatable QueryEx I can only get the column name appear on the combobox (just the Column name). I'm searching here but I cant find any solution. How to make this code run?
You're looking for the DisplayMember and ValueMember properties.
Also, it's generally a bad practice to try to and manage your connection like this as it can potentially lead to leaked connections. In a WinForms environment, it's not as dangerous as it is in a web environment, but it is something to be cognizant of, especially if you have lots of WinForms clients talking to the same database. If you have an exception that is thrown in your NonQueryEx method from your code above and caught at a higher level, your SqlConnection will be left open.
See: https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql-server-connection-pooling?redirectedfrom=MSDN
The way you want to make your database calls is to wrap your construction of your SqlConnection object in a using block:
Example:
using (var cn = new SqlConnection(connectionString))
{
var cmd = new SqlCommand(...);
cmd.ExecuteNonQuery();
}
If you're wanting to use an abstraction layer to save yourself from typing, wrap your call within a using block within that layer. This is the #1 mistake that I see with ADO.Net code at new clients (in other words, this is an incredibly common mistake and don't let this criticism discourage you). ADO.Net manages connections behind the scenes. Opening and closing a connection does not actually terminate a connection to a database, it releases it to the pool so the next call to .Open or .Close can reuse that same connection. Holding onto it for any longer than necessary means that new connections may need to be created. Likewise, there is no guarantee when your SqlConnect() instances will be cleaned up by .Net, so if you have a repeated exception that is caught at a higher level, this can result in multiple connections waiting to be released until your SqlConnect class is garbage collected.

connect to tableau postgresql in C#

I want to connect to the tableau PostgreSQL server from my .Net framework to list all the reports and datasources published in the tableau server.
For doing this, I have done the following steps.
Added the npgsql.dll reference that i downloaded online
Added the below two namespaces in my class file
using NpgsqlTypes;
using Npgsql;
I added the connection sting as follows
I also tried with modifying the connection string with port value and renaming the DataSource to Server, Initial catalog to Database and provider Name to Npgsqll
My Method is as follows:
public DataTable getAllDataSourceNames()
{
DataTable dataSourceNames = new DataTable();
NpgsqlConnection conServer = new NpgsqlConnection(conString);
conServer.Open();
string command = #"select * from datasources";
NpgsqlDataAdapter sqlcmd = new NpgsqlDataAdapter(command,conServer);
sqlcmd.Fill(dataSourceNames);
return dataSourceNames;
}`
No error. I can build and run successfully the other links in the website. But cannot cannot establish connection to my postgresql server.
Any idea of how to establish the connection?
Working with Postgres Connection in c#:
private DataSet ds = new DataSet();
private DataTable dt = new DataTable();
public Form1()
{
InitializeComponent();
}
private void llOpenConnAndSelect_LinkClicked(object sender,
LinkLabelLinkClickedEventArgs e)
{
try
{
// PostgeSQL-style connection string
string connstring = String.Format("Server={0};Port={1};" +
"User Id={2};Password={3};Database={4};",
tbHost.Text, tbPort.Text, tbUser.Text,
tbPass.Text, tbDataBaseName.Text );
// Making connection with Npgsql provider
NpgsqlConnection conn = new NpgsqlConnection(connstring);
conn.Open();
// quite complex sql statement
string sql = "SELECT * FROM simple_table";
// data adapter making request from our connection
NpgsqlDataAdapter da = new NpgsqlDataAdapter(sql, conn);
// i always reset DataSet before i do
// something with it.... i don't know why :-)
ds.Reset();
// filling DataSet with result from NpgsqlDataAdapter
da.Fill(ds);
// since it C# DataSet can handle multiple tables, we will select first
dt = ds.Tables[0];
// connect grid to DataTable
dataGridView1.DataSource = dt;
// since we only showing the result we don't need connection anymore
conn.Close();
}
catch (Exception msg)
{
// something went wrong, and you wanna know why
MessageBox.Show(msg.ToString());
throw;
}
}
The following link may help you: Using PostgreSQL in your C# .NET application
Short answer -- no, not sure what's wrong. Your code doesn't raise any alarm bells.
Somewhat related, and it may help: I'm a big fan of the Connection StringBuilder with Npgsql. Here is a brief example:
NpgsqlConnectionStringBuilder sb = new NpgsqlConnectionStringBuilder();
sb.ApplicationName = "Tableau " + Environment.GetEvironmentVariable("USERNAME");
sb.Host = "1.2.3.4";
sb.Port = 5432;
sb.Username = "foo";
sb.Password = "bar";
sb.Database = "postgres";
sb.Pooling = false;
sb.Timeout = 120;
conServer = new NpgsqlConnection(sb.ToString());
It demistifies all of this and makes injecting parameters easy. I highly recommend you add the ApplicationName property so that when you are monitoring sessions, you will know who is who.

how to manupilate database through data grid

guys here is what i have come up with I cant figure out what is the prob that is not allowing me to update the tables in the database
guys I need ur help I need to update my data base through data grid using c# as of yet all that I am able to do is that I am able to see the values that are inside the sql server that I put directly.`
string sConnectionString = "Data Source=localhost;Initial Catalog=ScratchCardSystem2;Integrated Security=True;pooling=true";
SqlConnection objConn = new SqlConnection(sConnectionString);
objConn.Open();
string query = "SELECT * FROM store_adj_note_detail_1";
SqlDataAdapter dAdapter = new SqlDataAdapter(query,objConn);
//dAdapter.SelectCommand= new SqlCommand(query, objConn);
SqlCommandBuilder cBuilder = new SqlCommandBuilder(dAdapter);
DataTable dTable = new DataTable();
//fill the DataTable
dAdapter.Fill(dTable);
dataGridView1.DataSource = dTable;
dAdapter.Update(dTable);
OleDbCommandBuilder commandBuilder = new OleDbCommandBuilder(dAdapter);
Is missing.
MSDN says:
//Without the OleDbCommandBuilder this line would fail.
dAdapter.Update(dTable);
You are missing something that binds your datagridview to your datatable. The trick here is that you need a BindingSource.
Add the following before your '//fille the datatble' line
BindingSource bindSrc = new BindingSource();
Then change your datasource of your datagridview and add a source to your bindingsource as well, like this:
dataGridView1.DataSource = bindSrc;
bindSrc.DataSource = dTable;
EDIT: I forgot to mention a tiny thing: to update, you now have to refer to the datatable that is the source of your bindingSrouce, this is how I did it:
dAdapter.Update((DataTable)bindSrc.DataSource);
Might be possible just with the regular update(dTable), but if it doesn't, this probably fixes it
So this is basically what I used for my own form. On establish connection the connection opens and it fills up my datagridview1 with the data from store_adj_note_detail_1.
Notice I never declare my bindingSource... I don't know the reason either, but I tried declaring it with the rest of them (globally) and locally, both made the code break :/
The declaration of your BindingSource happens on the Design view of your form - just drag it from the toolbox on top of your form and it will show up with an icon like FileDialogs and Menustrips do. I personally only changed the Name property and didn't add any events.
It should give you the overview of everything you need to open a connection, use the bindingsource to link your datagridview and your dataTable, and update your database.
I got this code by editing my own code that I used for an access database, but SQL databases seem to work exactly the same way, just with different entities (sqlDataAdapter and the likes instead of OleDb...).
hope this helps you!
public partial class FrmDatabaseConnection : Form
{
// Connection, Adapter, DataTable, CommandBuilder, Bindingsource and command
private SqlDataAdapter adap;
private DataTable dataTable;
private SqlCommandBuilder commandBuilder;
private string sqlCommand = "SELECT * FROM store_adj_note_detail_1";
private SqlConnection conDB = new SqlConnection();
//To open connection and fill datagridview1
private void establishConnection()
{
try
{
conDB.ConnectionString = "Data Source=localhost;Initial Catalog=ScratchCardSystem2;Integrated Security=True;pooling=true";
conDB.Open();
// Set adapter, commandbuilder, datatable and bindingsource
adap = new SqlDataAdapter(sqlCommand, conDB.ConnectionString);
commandBuilder = new SqlCommandBuilder(adap);
bindSrc = new BindingSource();
dataTable = new DataTable();
// Fill it!
adap.Fill(dataTable);
dataGridView1.DataSource = bindSrc;
bindSrc.DataSource = dataTable;
}
catch (Exception ex)
{
MessageBox.Show("Unable to Open database, " + ex.Message,);
conDB.Close();
}
}
private bool saveToDatabase()
{
try
{
adap.Update((DataTable)bindSrc.DataSource);
}
catch (Exception ex)
{
MessageBox.Show("Unable to Update database, " + ex.Message);
return false;
}
}
}

Sqlite database utilites class

I am using SQlite as a database in a C# winforms application.
My project involves some select simple queries, inserts, deletes.
Currently, I have written all these sql, Ado.net queries in the codebehind.
For eg:
private void frmPlant_Load(object sender, EventArgs e)
{
FillData();
}
void FillData()
{
dataGridView1.AutoGenerateColumns = true;
string query = #"SELECT * FROM [Table1]";
using (SQLiteConnection conn = new SQLiteConnection(connString))
{
conn.Open();
da = new SQLiteDataAdapter(query, conn);
ds = new DataSet();
da.Fill(ds, "T1");
dt = ds.Tables[0];
dataGridView1.DataSource = ds;
dataGridView1.DataMember = "T1";
dataGridView1.Columns["TId"].HeaderText = "SNo";
dataGridView1.Columns["Tcode"].Visible = false;
dataGridView1.Columns["TID"].Width = 50;
dataGridView1.Columns["Tcode"].Width = 70;
}
}
I have quiet a bit of code like this which interacts with the DB.
Question: Instead of writing these ado.net connections, sql query in the code behind, I want to use a 2 tier/3tier architecture. This should involve writing all the database stuff(ado.net execute scalar, reader, sql queries in another DBUtilitesclass/project and simply calling this DBUtilitesclass from the code behind.
Please suggest any tutorials to do this.
PS: I am using sqlite which does not support stored procedures.
Thank u
Sun
Refer
http://www.switchonthecode.com/tutorials/csharp-tutorial-writing-a-dotnet-wrapper-for-sqlite
http://snipplr.com/view/41708/
http://www.codeproject.com/Articles/22165/Using-SQLite-in-your-C-Application
Hope this helps
Thanks
Deepu

What is the best way to connect to a local database that will be used by two apps?

I'm writting an application in C# that connects to a database that is used by other application. I'm coding the class that access the database like this:
class conexionBD
{
string connString;
protected void miConexion(string ruta)
{
connString = String.Concat("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=", ruta);
}
protected DataTable misEmpleados()
{
string query = "SELECT Fiel1, Field2 FROM Table1";
DataTable dTable = miDatatable(query);
return dTable;
}
protected DataColumn misDptos()
{
DataTable dTable = miDatatable("SELECT OtherField from OtherTable");
return dTable.Columns[0];
}
private DataTable miDatatable(string sqlQuery)
{
OleDbDataAdapter dAdapter = new OleDbDataAdapter(sqlQuery, connString);
OleDbCommandBuilder cBuilder = new OleDbCommandBuilder(dAdapter);
DataTable dTable = new DataTable();
dAdapter.Fill(dTable);
return dTable;
}
}
The app firts calls the method "miConexion" to set the path to the database in the hard disc. Then the app connects and disconnects each time I want to get the data stored in "Table1" and "OtherTable".
The database is likely to be accessed and modified by both apps at the same time. "Connecting and disconnecting" is the best way to access the database in this case?
there are 3 improvements you can make:
abstract the specific database adapter to the configuration file.
dispose of ado.net objects when you are finished with them
use transaction when reading and writing to/from the db.
The database is likely to be accessed and modified by both apps at the
same time.
Then you would need to use transactions.
Also check that you open and close connection and the connection remains open for the shortest possible time. OleDb stack is really old if this is a new application consider moving to ORM or at least ADO.NET.
Use an ORM like Entity Framework (EF) or NHibernate to manage the state of the object (if both applications are .Net)
I would recommend NHibernate as you are using OLE data adapter (but see if there are any connectors for the database you are using for EF as it is far easier to setup)..
This is the modification of the method "miDatatable", it connects to an Access Database:
private DataTable miDatatable(string sqlQuery)
{
using (OleDbConnection connDB = new OleDbConnection(connString))
{
OleDbDataAdapter dAdapter;
OleDbCommandBuilder cBuilder;
OleDbCommand command = new OleDbCommand();
DataTable dTable = new DataTable();
OleDbTransaction trans = null;
try
{
connDB.Open();
trans = connDB.BeginTransaction(IsolationLevel.ReadCommitted);
command.Connection = connDB;
command.Transaction = trans;
command.CommandText = sqlQuery;
dAdapter = new OleDbDataAdapter(sqlQuery, connDB);
cBuilder = new OleDbCommandBuilder(dAdapter);
dAdapter.SelectCommand.Transaction = trans;
dAdapter.Fill(dTable);
trans.Commit();
}
catch
{
try
{
trans.Rollback();
}
catch { }
}
return dTable;
}
}

Categories

Resources