Code stops working after convering flat MDB to SQL-linked mdb - c#

I have modified my code to count records in each table inside an mdb file. It works flawlessly, until it hits an MDB file using linked tables, which point to a SQL server. The code cannot be modified to point to the SQL server directly, it is for an in-place software upgrade scenario.
How can I modify this code to work with regular as well as linked tables?
using System;
using System.Linq;
using System.Text;
using System.Data;
using System.Data.OleDb;
using System.Diagnostics;
using System.Collections;
using System.Data.Common;
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string[] databases = new string[3];
databases[0] = "data.mdb";
databases[1] = "chunk.mdb";
databases[2] = "transactions.mdb";
DateTime dt = DateTime.Now;
string filename = "Results-" + dt.Hour + "_" + dt.Minute + "_" + dt.Second + ".txt";
System.IO.StreamWriter file = new System.IO.StreamWriter(filename);
foreach(string db in databases)
{
file.WriteLine("##########BEGIN " + db + "##########\r\n");
Console.Write("Processing " + db + " Database . . . ");
string strAccessConn = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\financial\" + db;
DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.OleDb");
DataTable userTables = null;
DataSet myDataSet = new DataSet();
OleDbConnection conn = new OleDbConnection(strAccessConn);
using (DbConnection connection = factory.CreateConnection())
{
connection.ConnectionString = #"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\financial\DATA\" + db;
string[] restrictions = new string[4];
restrictions[3] = "Table";
try
{
connection.Open();
}
catch
{
Console.WriteLine("Error opening MDB file. Please ensure it is in the correct location");
}
userTables = connection.GetSchema("Tables", restrictions);
}
ArrayList tables = new ArrayList();
for (int i=0; i < userTables.Rows.Count; i++)
tables.Add(userTables.Rows[i][2].ToString());
foreach (string tbl in tables)
{
string queryString = "SELECT COUNT(*) FROM " + "[" + tbl + "]";
OleDbCommand command = new OleDbCommand(queryString, conn);
command.Connection.Open();
try
{
int records = (int)command.ExecuteScalar();
file.WriteLine("{0,-45}" + records,tbl);
}
catch (OleDbException e)
{
Console.WriteLine(e + "OLEDB Exception Occured.");
}
command.Connection.Close();
}
file.WriteLine("\r\n##########END " + db + "##########");
Console.WriteLine("Done!\n");
}
file.Close();
Console.WriteLine(#"All Databases Complete. Press any key to continue...");
Console.Read(); // Press any key to continue...
System.Diagnostics.Process.Start("notepad.exe",filename);
}
}
}

Hi I believe that can't be done with ado.net, I had the same scenario some years ago with ado.net 1. You have to use ADOX.
here is a list of ADOX examples that can be useful
http://allenbrowne.com/func-adox.html
ADOX does not make a difference between table and linked tables. ill take a look to my hard drive and I may post an example later.
you should execute your query with ADOX and you won't have the same problem that you have with ADO.net

You can also do this with DAO.

Related

How to print the results of a stored procedure onto specific positions in a text file?

I need to define the start and end positions of the results of my stored procedure, which needs to written into a text file.
For example, my stored procedure has 5 columns. When the C# program runs, it executes the SP, and writes all data from the 5 columns onto the text file. The problem is that I need each column to write a specific points in the file as shown below:
This image is the spec / positions of where the results actually need to display on the text file.
This is the code I have so far:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Data.SqlClient;
using System.Data;
namespace TestApp1
{
class Program
{
static void Main(string[] args)
{
string datetime = DateTime.Now.ToString("yyyyMMddHHmmss");
string LogFolder = #"C:\Log\";
try
{
//Declare Variables and provide values
string FileNamePart = "Customer";//Datetime will be added to it
string DestinationFolder = #"C:\TestDownload";
//string TableName = "Dbo.TBL_FAQ";
string FileDelimiter = ","; //You can provide comma or pipe or whatever you like
string FileExtension = ".txt"; //Provide the extension you like such as .txt or .csv
//Create Connection to SQL Server in which you like to load files
SqlConnection SQLConnection = new SqlConnection();
SQLConnection.ConnectionString = #"<ConnectionString>";
//Read data from table or view to data table
string query = "EXEC StoredProcedure";
SqlCommand cmd = new SqlCommand(query, SQLConnection);
SQLConnection.Open();
DataTable d_table = new DataTable();
d_table.Load(cmd.ExecuteReader());
SQLConnection.Close();
//Prepare the file path (Create and name file within folder)
string FileFullPath = DestinationFolder + "\\" + FileNamePart + "_" + datetime + FileExtension;
StreamWriter sw = null;
sw = new StreamWriter(FileFullPath, false);
// Write the Header Row to File
int ColumnCount = d_table.Columns.Count;
for (int ic = 0; ic < ColumnCount; ic++)
{
sw.Write(d_table.Columns[ic]);
if (ic < ColumnCount - 1)
{
sw.Write(FileDelimiter);
}
}
sw.Write(sw.NewLine);
// Write All Rows to the File
foreach (DataRow dr in d_table.Rows)
{
for (int ir = 0; ir < ColumnCount; ir++)
{
if (!Convert.IsDBNull(dr[ir]))
{
sw.Write(dr[ir].ToString());
}
if (ir < ColumnCount - 1)
{
sw.Write(FileDelimiter);
}
}
sw.Write(sw.NewLine);
}
sw.Close();
}
catch (Exception exception)
{
// Create Log File for Errors
using (StreamWriter sw = File.CreateText(LogFolder
+ "\\" + "ErrorLog_" + datetime + ".log"))
{
sw.WriteLine(exception.ToString());
}
}
}
}
}

Some Excel Files not moving from Shared Path to SQL Server

We have an application where the data in Excel file (present in shared path) moves to Database. In case of any error, the files moves to error folder by writing the error in a log file.It uses a windows service for the operation.
Sometimes the file doesn't have any error still moves to error folder by writing log External table is not in the expected format. But the same file uploading again for once or multiple times, its moving to Database without any errors.
The windows service, DB and shared path are present in XP Server. Application was running fine all these years. But in the recent days, above mentioned problem is occurring for almost every file.
We have installed Microsoft 2003, 2007,2012 office components and access engines too. But still the issue still persists.
I am mentioning the Windows service code below. Pls help. Thanks in advance.
using System.IO;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Data.SqlClient;
using System.Data.OleDb;
using System.Data.Common;
namespace Impexp_Service
{
public partial class Service1 : ServiceBase
{
System.Timers.Timer T1 = new System.Timers.Timer();
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
///start
///
{
SqlConnection strconnection = new SqlConnection();
strconnection.ConnectionString = #"Data Source=XXXXXX;Initial Catalog=XXXX;User ID=XX;Password=XXXXXX;";
strconnection.Open();
// To get the all files placed at the shared path
DirectoryInfo directory = new DirectoryInfo(#"D:\Impexp\Data\");
FileInfo[] files = directory.GetFiles("*.xlsx");
foreach (var f in files)
{
string path = f.FullName;
// TO establish connection to the excel sheet
string excelConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=1\";";
//Create Connection to Excel work book
OleDbConnection excelConnection = new OleDbConnection(excelConnectionString);
excelConnection.Open();
//Create OleDbCommand to fetch data from Excel
OleDbCommand cmd = new OleDbCommand("Select * from [Report$]", excelConnection);
DbDataReader dr = cmd.ExecuteReader();
// OleDbDataReader dReader;
// dReader = cmd.ExecuteReader();
SqlBulkCopy sqlBulk = new SqlBulkCopy(strconnection);
//Give your Destination table name
sqlBulk.DestinationTableName = "imp_master_test";
sqlBulk.WriteToServer(dr);
excelConnection.Close();
File.Delete(path);
// To move error files to the error folder
/// end
T1.Interval = 20000;
T1.Enabled = true;
T1.Start();
T1.Elapsed += new System.Timers.ElapsedEventHandler(T1_Elapsed);
}
}
}
void T1_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
T1.Enabled = false;
try
{
SqlConnection strconnection = new SqlConnection();
strconnection.ConnectionString = #"Data Source=10.91.XXXXXX;Initial Catalog=XXXXX;User ID=XXXXX;Password=XXXXX;";
strconnection.Open();
// To get the all files placed at the shared path
DirectoryInfo directory = new DirectoryInfo(#"D:\Impexp\Data\");
FileInfo[] files = directory.GetFiles("*.xlsx");
foreach (var f in files)
{
string path = f.FullName;
// TO establish connection to the excel sheet
string excelConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=1\";";
//Create Connection to Excel work book
OleDbConnection excelConnection = new OleDbConnection(excelConnectionString);
try
{
excelConnection.Open();
//Create OleDbCommand to fetch data from Excel
OleDbCommand cmd = new OleDbCommand("Select * from [Report$]", excelConnection);
DbDataReader dr = cmd.ExecuteReader();
// OleDbDataReader dReader;
// dReader = cmd.ExecuteReader();
SqlBulkCopy sqlBulk = new SqlBulkCopy(strconnection);
//Give your Destination table name
sqlBulk.DestinationTableName = "imp_master_prod";
sqlBulk.WriteToServer(dr);
excelConnection.Close();
File.Delete(path);
}
// To move error files to the error folder
catch (Exception exp)
{
excelConnection.Close();
File.Move(path, Path.Combine(#"D:\Impexp\error\", f.Name));
string path1 = #"D:\Impexp\error\error.txt";
if (File.Exists(path1))
{
// Create a file to write to.
using (StreamWriter sw = File.AppendText(path1))
{
sw.WriteLine("File : " + path + " : " + exp.Message);
sw.Flush();
}
}
T1.Enabled = true;
T1.Start();
}
}
strconnection.Close();
// End of TRY 1
}
catch (UnauthorizedAccessException UAEx)
{
string path1 = #"D:\Impexp\error\error.txt";
if (File.Exists(path1))
{
// Create a file to write to.
using (StreamWriter sw = File.AppendText(path1))
{
sw.WriteLine(UAEx.Message);
sw.Flush();
}
}
T1.Enabled = true;
T1.Start();
}
catch (PathTooLongException PathEx)
{
string path1 = #"D:\Impexp\error\error.txt";
if (File.Exists(path1))
{
// Create a file to write to.
using (StreamWriter sw = File.AppendText(path1))
{
sw.WriteLine(PathEx.Message);
sw.Flush();
}
}
T1.Enabled = true;
T1.Start();
}
T1.Enabled = true;
T1.Start();
}
protected override void OnStop()
{
}
}
}
I did some searching regarding the OLEDB coms and newer versions of Excel. It seems as though a great many people are having compatibility issues with them.
Unfortunately, it doesn't look like Microsoft is giving this any attention. Microsoft announced the depreciation of OLEDB functionality many years ago, and they have stopped adding any kind of internal support in their Office products and SQL servers. In fact,
The official shutdown date for MSAccess Web Apps and Web Databases was April 2018. That being the case, an update to the server, the client version of windows, or the client version of Excel may have triggered this, and it doesn't look like there is going to be a fix. I myself have started using 3rd party packages (free ones are available) to handle the interop with office products because I was tired of banging my head against the wall to create workarounds. Honestly, I don't know why Access still exists if they are taking away the ability to programmatically connect to an Access database.
I know this doesn't fix your problem, but it's better to face the truth and move on than to try to fix something that isn't going to fix.
Looking at this question, this appears to be an issue with reading the excel file, not the SQL table. Try changing the Excel connection string.
string excelConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties=\"Excel 12.0;HDR=Yes;IMEX=1\";";
to
string excelConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties=Excel 12.0;HDR=Yes;IMEX=1\";
Also, looking at another answer, the root cause could be uploading newer versions of excel.
Are you using an Excel 2007 file with a connection string that uses: Microsoft.Jet.OLEDB.4.0 and Extended Properties=Excel 8.0?
You can change the string to some other as below:
public static string path = #"C:\src\RedirectApplication\RedirectApplication\301s.xlsx";
public static string connStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path + ";Extended Properties=Excel 12.0;";
OR
Change the connection string from the link below:
http://www.connectionstrings.com/excel-2007

Export multiple tables from SQL Server to XML for restore

I have a web application in C# / ASP.NET. I want to export all the database table's data, with the same unique key (Company ID). All the tables have this key (different for every company). I want to do that for future backup. Is it possible with Linq or classic C#? How can achieve this backup and restore?
One of the example to the solution is
using System.Data.SqlClient;
using System.Data;
using System.IO;
namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
var connStr = "Data Source=MOHSINWIN8PRO\\SQLEXPRESS;Initial Catalog=AB2EDEMO;Integrated Security=True";
var xmlFileData = "";
DataSet ds = new DataSet();
var tables = new[] {"Hospital", "Patient"};
foreach (var table in tables)
{
var query = "SELECT * FROM "+ table +" WHERE (Hospital_Code = 'Hosp1')";
SqlConnection conn = new SqlConnection(connStr);
SqlCommand cmd = new SqlCommand(query, conn);
conn.Open();
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(ds);
conn.Close();
conn.Dispose();
xmlFileData+=ds.GetXml();
}
File.WriteAllText("D://SelectiveDatabaseBackup.xml",xmlFileData);
}
}
}
this will create SelectiveDatabaseBackup.xml which can be later used to restore the backup
SaveFileDialog SD = new SaveFileDialog();
if (SD.ShowDialog() != System.Windows.Forms.DialogResult.Cancel)
{
System.IO.StreamWriter SW = new System.IO.StreamWriter(SD.FileName);
foreach (string str in checkedListBox1.CheckedItems)
{
string XMLSTR = //Heads.funtions.ConvertDatatableToXML(
Heads.funtions.fire_qry_for_string(string.Format("Select * from {0} FOR XML AUTO,TYPE, ELEMENTS ,ROOT('{0}')", str)); // , str);
SW.Write(XMLSTR);
SW.WriteLine("###TABLEEND###");
}
SW.Close();
//_CommonClasses._Cls_Alerts.ShowAlert("Clean Up Completed...!!!", "CleanUP", MessageBoxIcon.Information);
}

Showing the output query?

I'm trying to show the output of the query SELECT * FROM phpbb_topics
I'm running this from a C# console app, using the MySql connector api.
The query works fine when I run it phpmyadmin, and gives me a list of forum topics.
When I run it in the C# app remotely though, it doesn't seem to do anything.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql;
using MySql.Data;
namespace SqlConsoleSlr
{
class Program
{
static void Main(string[] args)
{
MySql.Data.MySqlClient.MySqlConnection mycon =
new MySql.Data.MySqlClient.MySqlConnection(GetConnectionString());
Console.WriteLine(GetConnectionString());
if (mycon.State != System.Data.ConnectionState.Open)
try
{
mycon.Open();
Console.WriteLine("we're in");
}
catch (System.Data.SqlClient.SqlException ex)
{
Console.WriteLine(ex);
}
MySql.Data.MySqlClient.MySqlCommand msc = new MySql.Data.MySqlClient.MySqlCommand("SELECT * FROM `phpbb_topics` ");
Console.WriteLine("completed"); /// gets to here, but doesn't show output of msc
Console.ReadLine();
}
public static string GetConnectionString()
{
string hostname = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx;";
string username = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxx;";
string dbname = "xxxxxxxxxxxxxxxxxxxxxxxx;";
string password = "xxxxxxxxxxxxxxxxxxxxxxxxxxx;";
string s = "Server=" + hostname + "User=" + username + "Database=" + dbname + "Password=" + password;
return s;
}
}
}
Is there some method I need to call on the query object?
The only one I could find is msc.BeginExecuteReader();, but that doesn't seem to change the execution either.
You will need to create a MYSQL Data Reader object.
MySql.Data.MySqlClient.MySqlDataReader read = msqlCommand.ExecuteReader();
and then you can output the records after you read.read() all of the records.
You have to create an object of MySQL Data Reader then execute the command.
MySql.Data.MySqlClient.MySqlCommand msc = new MySql.Data.MySqlClient.MySqlCommand("SELECT * FROM `phpbb_topics` ");
MySql.Data.MySqlClient.MySqlDataReader read = msqlCommand.ExecuteReader();
if(read != null)
{
//Sample output
while (read.Read())
{
int TopicID = Convert.ToInt32(read["Topic_ID"]);
string TopicName = Convert.ToString(read["Topic_Name"]);
Console.WriteLine(TopicID.ToString() + " : " + TopicName);
}
}

How to create an Access database at runtime in C#?

How can I create an Access Database at runtime in C#?
The first thing you need to do is get a COM reference to the Microsoft ADO Ext. X.X for DDL and Security. The X.X represents whatever version you happen to have on your machine. Mine used to be version 2.7, but with Visual Studio 2008, it was updated to 6.0.
alt text http://blog.jrpsoftware.com/content/binary/WindowsLiveWriter/CreateanAccessDatabaseinC_10DDD/AddReference_2.png
Once you have added the reference, ADOX will be added to the using section of your code.
alt text http://blog.jrpsoftware.com/content/binary/WindowsLiveWriter/CreateanAccessDatabaseinC_10DDD/Using_2.png
Next you will want to create the catalog for the database. Insert the filename you wish into the following string and pass it to the CatalogClass.
CatalogClass cat = new CatalogClass();
string tmpStr;
string filename = "Sample.MDB";
tmpStr = "Provider=Microsoft.Jet.OLEDB.4.0;";
tmpStr += "Data Source=" + filename + ";Jet OLEDB:Engine Type=5";
cat.Create(tmpStr);
The next step is to create the table and columns for your database. This is a pretty straight forward operation as shown in the example below.
Table nTable = new Table();
nTable.Name = "PersonData";
nTable.Columns.Append("LastName", DataTypeEnum.adVarWChar, 25);
nTable.Columns.Append("FirstName", DataTypeEnum.adVarWChar, 25);
nTable.Columns.Append("Address 1", DataTypeEnum.adVarWChar, 45);
nTable.Columns.Append("Address 2", DataTypeEnum.adVarWChar, 45);
nTable.Columns.Append("City", DataTypeEnum.adVarWChar, 25);
nTable.Columns.Append("State", DataTypeEnum.adVarWChar, 2);
nTable.Columns.Append("Zip", DataTypeEnum.adVarWChar, 9);
cat.Tables.Append(nTable);
The final step is very important or you will get error when you close your application. Once the all the tables and columns have been added, you will need to release the com objects properly and in the proper order.
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(nTable);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(cat.Tables);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(cat.ActiveConnection);
System.Runtime.InteropServices.Marshal.FinalReleaseComObject(cat);
That is it. You should now have a Access Database that you can write to. Hope this helps.
Reference: John Russell Plant - Create an Access Database in C#
Create a blank access database and store it in your resource files.
Now whenever you want to use it, fetch that database from your resources and copy it to wherever you want, rename it to whatever you want and execute your database setup script to create default tables and load values in them.
Try:
using ADOX; //Requires Microsoft ADO Ext. 2.8 for DDL and Security
using ADODB;
public bool CreateNewAccessDatabase(string fileName)
{
bool result = false;
ADOX.Catalog cat = new ADOX.Catalog();
ADOX.Table table = new ADOX.Table();
//Create the table and it's fields.
table.Name = "Table1";
table.Columns.Append("Field1");
table.Columns.Append("Field2");
try
{
cat.Create("Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=" + fileName + "; Jet OLEDB:Engine Type=5");
cat.Tables.Append(table);
//Now Close the database
ADODB.Connection con = cat.ActiveConnection as ADODB.Connection;
if (con != null)
con.Close();
result = true;
}
catch (Exception ex)
{
result = false;
}
cat = null;
return result;
}
http://zamirsblog.blogspot.com/2010/11/creating-access-database.html
This article from John Russell Plant explains how you'd do it in specific detail with code samples. There are three steps:
Create the catalog.
Create the tables.
Release the relevant COM objects.
static void IF_EXISTS_DELETE_AND_CREATE(string cn)
{
//cn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source =";
//cn += AppDomain.CurrentDomain.BaseDirectory.ToString() + "test.mdb";
try
{
OleDbConnection connection = new OleDbConnection(cn);
object[] objArrRestrict;
objArrRestrict = new object[] { null, null, null, "TABLE" };
connection.Open();
DataTable schemaTable = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, objArrRestrict);
connection.Close();
string[] list;
if(schemaTable.Rows.Count > 0)
{
list = new string[schemaTable.Rows.Count];
int i = 0;
foreach (DataRow row in schemaTable.Rows)
{
list[i++] = row["TABLE_NAME"].ToString();
}
for ( i = 0; i < list.Length; i++)
{
if(list[i] == "TEMP")
{
string deletedl = "DROP TABLE TEMP";
using (OleDbConnection conn = new OleDbConnection(cn))
{
using (OleDbCommand cmd = new OleDbCommand(deletedl, conn))
{
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
}
break;
}
}
}
string ddl = "CREATE TABLE TEMP (USERID INTEGER NOT NULL,[ADATE] TEXT(20), [ATIME] TEXT(20))";
using(OleDbConnection conn = new OleDbConnection(cn))
{
using(OleDbCommand cmd = new OleDbCommand(ddl, conn))
{
conn.Open();
cmd.ExecuteNonQuery();
conn.Close();
}
}
}
catch (System.Exception e)
{
string ex = e.Message;
}
}

Categories