I'm writing some software in C# that will perform queries on Visual FoxPro datafiles over time. I need to be able to close tables, especially those that are opened exclusively ("Mode=Share Exclusive" in the Connection String), but the only way I can seem to do that is by closing the entire OleDbConnection.
The VFP OLE DB Provider supports some syntax from VFP itself, but commands that would close a table in standard VFP, such as USE, either do not work, or throw an exception (I can't recall which command threw an exception at the moment).
Currently, each instance of a class has its own OleDbConnection property, so that if I need to, I'm able to close it and release the table it works on. While this works, it's not optimal, and I'd prefer to have 1 connection instance.
// Elsewhere, ideally one connection for the entire process,
// if I'm able to release locks
public OleDbConnection Connection { get; } = new OleDbConnect();
// ...
if(Connection.State == ConnectionState.Closed) {
Connection.ConnectionString = "Provider=vfpoledb.dll;Data Source=J:\\epdata\\;Mode=Share Exclusive"
Connection.Open();
}
OleDbCommand cmd = new OleDbCommand("SET DELETED OFF", Connection);
cmd.ExecuteNonQuery();
cmd.CommandText = "SELECT * FROM tran";
OleDbDataAdapter adap = new OleDbDataAdapter(cmd);
DataTable table = new DataTable();
adap.Fill(table);
// Something here to release the lock on the tran table
This works to the point where it will select the data and lock the table for exclusive use by the current OleDbConnection, but I cannot find any way to release that exclusive lock without closing the entire connection, which I'm trying to avoid having to do.
I don't see a point opening a connection exclusively and then using an adapter to fill a table, after which you want to release lock. You don't need a connection in the first place, adapter opens and closes the connection as needed:
DataTable table = new DataTable();
new OleDbDataAdapter("SELECT * FROM tran",
#"Provider=vfpoledb;Data Source=J:\epdata;Deleted=off")
.Fill(table);
Related
I am trying to have a MySQL connection open in the main form. However, O am having trouble trying use the connection in other forms.
How should I set it up so that I only need to open the connection once in the whole program, and use the same connection to get data from database.
Or should I have a new connection open in each form?
Thank you
It is better to use using statement with SQL connection as follow:
using (SqlConnection connection = new SqlConnection(connectionString))
{
//Your code goes here
}
and make the connection string in App.config file.
You don't want to just leave a connection open the whole time the app is running. It's better to create a single function that you can call repeatedly if your goal is to simplify code readability. The below example is as basic as it gets, but you'll need to do a bit more for stored procedures and Parameter objects not in a query string. All this will do is fill a datatable.
public DataTable RunQuery(string query)
{
//connectionString should come from your configuration or a constant that is a part of this class
DataTable dt = new DataTable();
using (SqlCommand cmd = new SqlConnection(connectionString))
{
cmd.CommandText = query;
cmd.Connection.Open();
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
sda.Fill(dt);
}
cmd.Connection.Close();
}
return dt;
}
Calling it is easy.
RunQuery("Select * from myData");
Basically, you have to open your MySqlConnection once, and then reuse your connection with using, or by checking it´s state. It is the same as every ADO.NET library. Using the usingstatement you have guarantee that the object will be disposed and all resources released.
This link has everithing you need about working with MySql: https://www.codeproject.com/Articles/43438/Connect-C-to-MySQL
I am trying to learn about how to work with databases in C# and I have gotten to a part in a tutorial when I have to work with DataSet , SqlDataAdapter and SqlCommandBuilder.This is the code I wrote in the example in the tutorial:
public void InitData() {
//instantiate the connection
conn = new SqlConnection("Data Source=.\\SQLEXPRESS;AttachDbFilename=\"D:\\Projects IDE\\Visual Studio\\Exercitii\\Console.app\\WindowsFormsApplication1\\WindowsFormsApplication1\\PlanetWrox.mdf\";Integrated Security=True;User Instance=True");
//1.instantiate a new DataSet
dsCustomers = new DataSet();
//2.init SqlDataAdapter with select command and connection
daCustomers = new SqlDataAdapter("SELECT Id ,Name, SortOrder FROM Genre", conn);
// 3. fill in insert, update, and delete commands
SqlCommandBuilder cmdBldr = new SqlCommandBuilder(daCustomers);
// 4. fill the dataset
daCustomers.Fill(dsCustomers, tableName);
}
public void btnUpdateClicked(object sender, EventArgs e) {
// write changes back to DataBase
daCustomers.Update(dsCustomers, tableName);
}
There are a couple of things I do not understand here:
The first thing I noticed is that I do not have to open and close the database.From what limited knoledge I have about databases I know that in order to acces the data you have to open a connection to it and after you are done you have to close it.This must happen somewhere behind the scene.Is that righT? If that is so witch method does that?
The second question is regarding the SqlDataAdapter and SqlCommandBuilder.I do not understand what does SqlCommandBuilder does here.Isen't the SqlDataAdapter the one that is executing the sql query?
The first thing I noticed is that I do not have to open and close the
database.
SqldataAdapter.Fill will open/close the connection for you.
If the IDbConnection is closed before Fill is called, it is opened to
retrieve data and then closed. If the connection is open before Fill
is called, it remains open.
The SqlCommandBuilder generates INSERT, UPDATE, or DELETE statements from the metadata of your provided select-statement. On this way you can call daCustomers.Update and all changes made to the DataSet will automatically be updated in the database.
dsCustomers.Fill opens and closes connection for you.
SqlCommandBuilder creates insert, update, and delete based on your select statement.
ADO.NET handles that task for you, when you Fill your table with data
//instantiate the connection
using (SqlConnection conn = new SqlConnection("Data Source=.\\SQLEXPRESS;AttachDbFilename=\"D:\\Projects IDE\\Visual Studio\\Exercitii\\Console.app\\WindowsFormsApplication1\\WindowsFormsApplication1\\PlanetWrox.mdf\";Integrated Security=True;User Instance=True"))
{
//1.instantiate a new DataSet
dsCustomers = new DataSet();
//2.init SqlDataAdapter with select command and connection
daCustomers = new SqlDataAdapter("SELECT Id ,Name, SortOrder FROM Genre", conn);
// 3. fill in insert, update, and delete commands
SqlCommandBuilder cmdBldr = new SqlCommandBuilder(daCustomers);
// 4. fill the dataset
daCustomers.Fill(dsCustomers, tableName);
}
This would automatically close the connection and Dispose, without you having to bother about it.
Fill will make the all the resources locked that are involved in the process.
Also as per the sql settings it may block other resources too.
If you are using this code for some real time work..Please choose it only if you need this.
For your first thing:
We use conn.open(); to open the connection and conn.close(); to close the connection.
Here in your program you are not connecting to database like to sqlserver. You have provided shown physical path to the file.
See the below for second thing:
SqlCommandBuilder Class
Firstly, For Those who would like to ask WHY on earth am I DOWNSIZING from SQL SERVER to ACCESS, let me tell you the scenario.
There are some PC's with very low configuration, (256 MB RAM, 2GHzProcessor) I cannot install SQL Server. Hence I want major operations to carry out on SQL server and some data retrieving and auditing work to be done on Slower machine.
So here we go:
I want to copy table from SQL Server to MS Access 2007. I tried:
1)Connect to sql server, fill a datatable object by reading table from sql server.
2) Create a connection to MS Access, and use Dataadapter.Update method to update table to MS Access database.
However 2nd step is not working although its not throwing any error. Here is my code:
SqlConnection cnn = new SqlConnection(#"initial catalog=DBTempleERM;user id=aditya;password=Aditya_ravi$;Data Source=adityalappy\sqlexpress");
SqlCommand cmd = new SqlCommand("SELECT * FROM donationdetails", cnn);
cnn.Open();
System.Data.SqlClient.SqlDataAdapter sDA = new SqlDataAdapter(cmd);
DataTable donationdetails = new DataTable();
sDA.MissingSchemaAction = MissingSchemaAction.AddWithKey;
sDA.Fill(donationdetails);
MessageBox.Show(donationdetails.Rows.Count.ToString());
OleDbConnection oleConn = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Jet OLEDB:Database Password=Aditya_ravi$;Data Source=C:\dbt.accdb");
oleConn.Open();
OleDbCommand oleComm = new OleDbCommand();
OleDbDataAdapter oDA = new OleDbDataAdapter(oleComm);
OleDbCommandBuilder oCb = new OleDbCommandBuilder(oDA);
oDA.Update(donationdetails);
No error is thrown at the end of the execution, but I cannot see any records copied from SQL Server to MS Access.
I learnt that SQL Bulk copy cannot be used to copy from SQL Server to Access.
I also want to add the primary key from SQL Server table to MS Access table.
Why dont you use SSIS to do this for you.
You can create a SSIS package to copy a sql table to MS access.
If you want to initiate by .NET then create a SSIS package and call it from .NET
For details
At this point, oDA is not connected to any table on the Access side:
oDA.Update(donationdetails);
So even though you have all the data in a DataTable, you haven't got a target to copy it into.
I don't think this is the best approach, but that's the core of why your code isn't working as it is.
Ancient question, but I'm betting the RowState of all your rows in donationdetails were Unchanged, so the DataAdapter treats them as "I don't need to do anything with this row."
You can use dataset object instead of datatable.
DataSet ds=new DataSet();
sDA.Fill(ds,tablename);
oDA.Update(ds);
I can connect to MySQL database from my WinForms app fine. The question is once I am logged in how can I perform multiple select statements without having to login again?
MySqlConnection connection = new MySqlConnection(MyConString);
connection.Open();
MySqlCommand command = connection.CreateCommand();
MySqlDataReader Reader;
command.CommandText = "select id from user ";
Then I want to perform a select statement for another table without having to create connection again.
How do I dothis?
I can't seem to just do connection.CreateCommand.
As long as the queries are within the same block, you can use the same connection.. However, once closed, you need to re-open it.
using( YourConnectionObject )
{
... open connection ...
... create your sql querying object... and command
SQLCommand.Connection = YourConnectionObject;
Execute your Query
SQLCommand.CommandText = "a new sql-select statement";
Execute your NEW query while connection still open/active
SQLCommand.CommandText = "a third sql-select statement";
Execute your THIRD query while connection still open/active
... close your connection
}
However, in your application, you can have a single "connection" object like at the application level, or at a form level with the necessary login / connection settings stuff. Then, internally to each form, you can
Open
Run Query
Run Query
Run Query
Close
as needed.
I see you're using a DataReader. You can only have 1 DataReader open at a time per connection. using blocks come in handy for those:
using( var reader = myCommand.ExecuteReader() ) {
while (reader.Read()) {
// get values, do stuff
}
}// reader gets closed
You only hint at it in the code in your question (currently), but it's possible that is part of your problem. You haven't shown how you're using the DataReader, so I'm not certain. Just a possibility.
How can I get a DataSet with all the data from a SQL Express server using C#?
Thanks
edit: To clarify, I do want all the data from every table. The reason for this, is that it is a relatively small database. Previously I'd been storing all three tables in an XML file using DataSet's abilities. However, I want to migrate it to a database.
You can use the GetSchema method to get all the tables in the database and then use a data adapter to fill a dataset. Something like this (I don't know if it compiles, I just paste some code and change it a bit):
DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.SqlClient");
DataTable tables = null;
DataSet database = new DataSet();
using (DbConnection connection = factory.CreateConnection())
{
connection.ConnectionString = "Data Source=(local);Initial Catalog=Northwind;Integrated Security=True";
string[] restrictions = new string[4];
// Catalog
restrictions[0] = "Northwind";
// Owner
restrictions[1] = "dbo";
// Table - We want all, so null
restrictions[2] = null;
// Table Type - Only tables and not views
restrictions[3] = "BASE TABLE";
connection.Open();
// Here is my list of tables
tables = connection.GetSchema("Tables", restrictions);
// fill the dataset with the table data
foreach (DataRow table in tables.Rows)
{
string tableName = table["TABLE_NAME"].ToString();
DbDataAdapter adapter = factory.CreateDataAdapter();
DbCommand command = factory.CreateCommand();
command.Connection = connection;
command.CommandType = CommandType.Text;
command.CommandText = "select * from [" + tableName + "]";
adapter.SelectCommand = command;
adapter.Fill(database, tableName);
}
}
EDIT:
Now I refactored it a bit and now it's working as it should. The use of DbConnection and DbProviderFactories is for database engine abstraction, I recommend using it so you can change the database engine changing this line and the connection string:
DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.OracleClient");
The GetSchema method will retrive all tables from your database to a DataTable and then we get all the data from each table to the DataSet using the DataAdapter.
I think you need to narrow down the question somewhat... All the data? You mean, all the data in every table in every database? Well, the only answer to that is, a lot of code.
To connect to and talk to a SQL Server Express database engine, use the classes in the System.Data.SqlClient namespace, namely:
SqlConnection: Connect to the database
SqlCommand: Talk to the database
SqlDataReader: Iterate over data retrieved from the database
You can check the MSDN pages for all of these classes by clicking on the links above.
Here are some overview-links with more information:
CodeProject: Beginners guide to accessing SQL Server through C#
DevHood: Accessing SQL Server Data in C# with ADO.NET
Note that by and large, you use a SQL Server Express database engine the same way as the full SQL Server product, the difference is more in the tools you get with it, and some limitations in the express engine. Other than that you can just use the classes and language that you would use for a normal SQL Server database engine installation.
If this post didn't answer your question, please elaborate, and you have a higher chance of getting the answer you seek.
This can be done by using dataAdapter class.