c# datatable Cannot update. Database or object is read-only - c#

private void Form1_Load(object sender, EventArgs e)
{
GetDataTable(#"C:\Documents and Settings\agordon\Desktop\ACTIVITYEX.log");
}
public System.Data.DataTable GetDataTable(string strFileName)
{
System.Data.OleDb.OleDbConnection conn =
new System.Data.OleDb.OleDbConnection
("Provider=Microsoft.Jet.OleDb.4.0; Data Source = "
+ System.IO.Path.GetDirectoryName(strFileName)
+ ";Extended Properties = \"Text;HDR=YES;FMT=TabDelimited\"");
conn.Open();
string strQuery = "SELECT * FROM [" + System.IO.Path.GetFileName(strFileName) + "]";
System.Data.OleDb.OleDbDataAdapter adapter = new System.Data.OleDb.OleDbDataAdapter(strQuery, conn);
System.Data.DataTable ds = new System.Data.DataTable("CSV File");
adapter.Fill(ds);
return ds;
}
when THE SAME file is named .csv it does not give me an error; however when i rename it to .log it says Cannot update. Database or object is read-only. on adapter.Fill
is this a compiler error?

An old post, but I just stepped into that problem.
Please refer to this article : https://support.microsoft.com/en-us/kb/245407
Long story short : Jet Engine only accepts a few file extension when reading CSV File (Extended properties=TEXT,etc..).
Solutions :
rename your file in a temp folder when reading it
read it with another mecanism than JET (standard File.io.ReadAllLines)
Add the extension in the windows registry as pointed out by antonio Bukala

No, it's a not a compiler error. If anything it's an error from the OleDb Jet engine. I have ran into enough problems with Jet in the past so I usually avoid it. You might save yourself lots of debugging time by using TextFieldParser.

*.log is disabled extension, AFAIK only way is registry change on machine that will run this code, see MS Knowledge base article

Related

Changing upload controller from supporting .xlsx to .csv

I have an MVC application which allows an admin user to upload 2 different excel file onto the system; the controller then creates a dataset with the excel data and then populates either a "Schools" or a "School2" database with the dataset using an SqlBulkCopy.
These uploads work perfect when I test them locally using IIS Express, although the same version deployed to AWS elastic beanstalk throws an error when I press the import button. As far as I am aware, this is due to my AWS RDS needing access to the OleDB provider jet drivers; something which I can not do because these drivers can not just be installed on an AWS RDS like they can be on an EC2 instance.
So my plan is to change my upload controller around to accept .csv files instead of excel files. This should solve my problem and allow my upload buttons to work after being deployed on AWS. Could someone help me/point me in the right direction to change my controller to support .csv instead of excel please?
Upload Controller:
namespace CampBookingSys.Controllers
{
public class UploadController : Controller
{
SqlConnection con = new SqlConnection(#"Data Source=bookingdb.cwln7mwjvxdd.eu-west-1.rds.amazonaws.com,1433;Initial Catalog=modeldb;User ID=craig1990;Password=27Oct90!;Database=modeldb;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False");
OleDbConnection Econ;
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(HttpPostedFileBase file)
{
string filename = Guid.NewGuid() + Path.GetExtension(file.FileName);
string filepath = "/excelfolder/" + filename;
file.SaveAs(Path.Combine(Server.MapPath("/excelfolder"), filename));
InsertExceldata(filepath, filename);
return View();
}
[HttpPost]
public ActionResult Index2(HttpPostedFileBase file)
{
string filename = Guid.NewGuid() + Path.GetExtension(file.FileName);
string filepath = "/excelfolder/" + filename;
file.SaveAs(Path.Combine(Server.MapPath("/excelfolder"), filename));
InsertExceldata2(filepath, filename);
return RedirectToAction("Index");
}
private void ExcelConn(string filepath)
{
string constr = string.Format(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source={0};Extended Properties=""Excel 12.0 Xml;HDR=YES;""", filepath);
Econ = new OleDbConnection(constr);
}
private void InsertExceldata(string filepath, string filename)
{
string fullpath = Server.MapPath("/excelfolder/") + filename;
ExcelConn(fullpath);
string query = string.Format("Select * from [{0}]", "Sheet1$");
OleDbCommand Ecom = new OleDbCommand(query, Econ);
Econ.Open();
DataSet ds = new DataSet();
OleDbDataAdapter oda = new OleDbDataAdapter(query, Econ);
Econ.Close();
oda.Fill(ds);
DataTable dt = ds.Tables[0];
SqlBulkCopy objbulk = new SqlBulkCopy(con);
objbulk.DestinationTableName = "dbo.Schools";
objbulk.ColumnMappings.Add("AcademicYear", "AcademicYear");
objbulk.ColumnMappings.Add("RollNumber", "RollNumber");
objbulk.ColumnMappings.Add("OfficialSchoolName", "OfficialSchoolName");
objbulk.ColumnMappings.Add("Address1", "Address1");
objbulk.ColumnMappings.Add("Address2", "Address2");
objbulk.ColumnMappings.Add("Address3", "Address3");
objbulk.ColumnMappings.Add("Address4", "Address4");
objbulk.ColumnMappings.Add("County", "County");
objbulk.ColumnMappings.Add("Eircode", "Eircode");
objbulk.ColumnMappings.Add("LocalAuthority", "LocalAuthority");
objbulk.ColumnMappings.Add("X", "X");
objbulk.ColumnMappings.Add("Y", "Y");
objbulk.ColumnMappings.Add("ITMEast", "ITMEast");
objbulk.ColumnMappings.Add("ITMNorth", "ITMNorth");
objbulk.ColumnMappings.Add("Latitude", "Latitude");
objbulk.ColumnMappings.Add("Longitude", "Longitude");
con.Open();
objbulk.WriteToServer(dt);
con.Close();
}
private void InsertExceldata2(string filepath, string filename)
{
string fullpath = Server.MapPath("/excelfolder/") + filename;
ExcelConn(fullpath);
string query = string.Format("Select * from [{0}]", "Sheet1$");
OleDbCommand Ecom = new OleDbCommand(query, Econ);
Econ.Open();
DataSet ds = new DataSet();
OleDbDataAdapter oda = new OleDbDataAdapter(query, Econ);
Econ.Close();
oda.Fill(ds);
DataTable dt = ds.Tables[0];
SqlBulkCopy objbulk = new SqlBulkCopy(con);
objbulk.DestinationTableName = "dbo.School2";
objbulk.ColumnMappings.Add("RollNumber", "RollNumber");
objbulk.ColumnMappings.Add("OfficialSchoolName", "OfficialSchoolName");
objbulk.ColumnMappings.Add("Address1", "Address1");
objbulk.ColumnMappings.Add("Address2", "Address2");
objbulk.ColumnMappings.Add("Address3", "Address3");
objbulk.ColumnMappings.Add("Address4", "Address4");
objbulk.ColumnMappings.Add("County", "County");
objbulk.ColumnMappings.Add("Eircode", "Eircode");
objbulk.ColumnMappings.Add("PhoneNumber", "PhoneNumber");
objbulk.ColumnMappings.Add("Email", "Email");
objbulk.ColumnMappings.Add("PrincipalName", "PrincipalName");
objbulk.ColumnMappings.Add("DeisSchool", "DeisSchool");
objbulk.ColumnMappings.Add("SchoolGender", "SchoolGender");
objbulk.ColumnMappings.Add("PupilAttendanceType", "PupilAttendanceType");
objbulk.ColumnMappings.Add("IrishClassification", "IrishClassification");
objbulk.ColumnMappings.Add("GaeltachtArea", "GaeltachtArea");
objbulk.ColumnMappings.Add("FeePayingSchool", "FeePayingSchool");
objbulk.ColumnMappings.Add("Religion", "Religion");
objbulk.ColumnMappings.Add("OpenClosedStatus", "OpenClosedStatus");
objbulk.ColumnMappings.Add("TotalGirls", "TotalGirls");
objbulk.ColumnMappings.Add("TotalBoys", "TotalBoys");
objbulk.ColumnMappings.Add("TotalPupils", "TotalPupils");
con.Open();
objbulk.WriteToServer(dt);
con.Close();
}
}
}
My first advice is to do bulk inserts in the DBMS, not in code. Doing them via code is only prone to add addtional issues.
As far as parsing the .xlsx files go, the OleDB driver is propably unessesary. There are a few basic rules for working with office formats:
if you can limit it to the new ones (.xlsx), you can use the OpenXML SDK. Or any of the Wrappers people made around it. Or even just the .ZipArchive and XMLReader classes.
if you need to support the old formats (.xls) too, you got to use the (t)rusty Office COM Interop. This has all the usual issue of COM Interop, and aditionally needs office installed and a Interactive session
for any given Display Technology and Problem, there might be a 3rd option. But those are few and far in between. As we always got the Interop to fall back on, we never developed a complete Office processing class like so many other languages have.
I would put OlebDB in that last category - a rare and very specific solution.
It always advise for using the first option.
And Officer COM Interop should be silently burried, with the old formats being removed from the file format options. Considering this is a WebApplication that will likely run as services, you will not get the nesseary interactive session anyway.
Of course accepting .csv is also an option. And indeed Excel has full .CSV support.

Create excel file from an object

I am looking for a library which would do something like that:
Lib.Configure.Cells(...)
Lib.CreateExcelFileFromMyObject<MyObject>(myObject);
I believe a long ago I come across such library but cant remember it's name.
May be some one can point me to the right direction.
I know two ways to read or write excel files.
As already said you can access excel files through the office interop interface as described here. This method is slow, but you can do almost everything what you can do with the gui of excel.
Use the OleDb database interface. This possibility is much faster than the first one, but its restricted to data. So as far as i know it is not possible to read/write formatting e.g. some background color of a cell. With the following function you will get the entire data of a sheet of an excel file at once:
private DataSet ConnectAndLoad(string filepath, string sheet)
{
DataSet data_set = new DataSet();
OleDbConnection oledbConn = new OleDbConnection(String.Format("Provider=Microsoft.Ace.Oledb.12.0;Data Source={0};Extended Properties=\"Excel 8.0;HDR=Yes;IMEX=1;\"", filepath));
string query = "Select * From [" + sheet + "$]";
try
{
oledbConn.Open();
OleDbCommand oledbCmd = new OleDbCommand(query, oledbConn);
OleDbDataAdapter ole_da = new OleDbDataAdapter(oledbCmd);
ole_da.Fill(data_set);
}
catch (OleDbException ex)
{
// do some error catching
}
finally
{
oledbConn.Close();
}
return data_set;
}
you can use
using Microsoft.Office.Interop
namespace to access the ms products
For that first you need to do is add that reference to your project

What would be a valid OleDbConnection ConnectionString for an uploaded file?

I am certain I have missed something obvious.
A simple task is before me: 'Upload an Excel (2003) file via ASP.NET on a Forms page and push the contents of that file to a DataTable in preparation for data- validation / storage'.
Those operations work fine already when applied to a locally stored edition of the file -- for that I simply utilize the OleDbConnection-ConnectionString "String.Format("Provider=Microsoft.Jet.OLEDB.4.0;Data Source={0};Extended Properties=Excel 8.0;", fileName)" from an OleDbDataAdapter.
However, trying to repeat that with an uploaded edition of the very same file (via a FileUpload control), on the line where I fill the OleDbDataAdapter I receive the error ["The Microsoft Jet database engine could not find the object "Sheet1$". Make sure the object exists and that you spell its name and the path name correctly."] An error so generic and painful -- still I'm unsure where to look next. I am guessing the connection-string structure is illegitimate for an uploaded file.
I searched through StackOverflow and MSDN and even around the web with no success thus far, but the search terms may be overly ubiquitous. Am I required to actually find a local repository for saving the uploaded file to prior to attempting a parse of it's content? Can I not simply construct a connection to a 'file in memory'? In case it concerns the answer, the uploaded files are not anticipated to ever exceed 200 kb in size.
Sincere thanks in advance for any assistance provided...
What I do in this situation is build a Parser class that will temporarily save the file, process it, then delete that temporary file when disposed. Something like:
public class ExcelParser : IDisposable
{
string filename;
string connStr = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source={0}; Extended Properties=\"Excel 12.0 Xml;HDR=YES\"";
public ExcelParser(HttpPostedFile file)
{
filename = String.Format("{0}{1}.xlsx", System.IO.Path.GetTempPath(), Guid.NewGuid().ToString());
file.SaveAs(filename);
}
public MyData Process()
{
OleDbConnection conn = new OleDbConnection(String.Format(connStr, filename));
conn.Open();
OleDbCommand cmd = new OleDbCommand("Select * From [Sheet1$]", conn);
OleDbDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
// Build Data to return
}
reader.Close();
conn.Close();
return data; // Return data you built
}
public void Dispose()
{
File.Delete(filename);
}
}
You could then use it as such:
using (ExcelParser parser = new ExcelParser(file))
{
var results = parser.Process();
// Do stuff
}

C# Open DBF file

I'm having a problem opening a DBF file - I need to open it, read everything and process it. I tried several solutions (ODBC/OLEDB), several connection string, but nothing worked so far.
The problem is, when I execute the SQL command to get everything from the file, nothing gets returned - no rows. What's even more odd, the content of the DBF file being opened get deleted.
See the code I have:
public override bool OpenFile(string fileName, string subFileName = "")
{
OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + Path.GetDirectoryName(fileName) + ";Extended Properties=dBASE IV;User ID=;Password=;");
try
{
if (con.State == ConnectionState.Closed) { con.Open(); }
OleDbDataAdapter da = new OleDbDataAdapter("select * from " + Path.GetFileName(fileName), con);
DataSet ds = new DataSet();
da.Fill(ds);
con.Close();
int i = ds.Tables[0].Rows.Count;
return true;
}
catch
{
return false;
}
}
I debugged the code and watched the file being opend in Windows Explorer. When it reached this line:
da.Fill(ds);
the size of the file dropped to only a few Bytes (from hundreds of kB).
My next thought was to make the DBF file read only. That however cause an "unexpected exception from an external driver".
So my question is - what the heck? I'm sure the file is not corrupt, it is a direct export from some DB. (No, I do not have access to that DB). I can also open that file in MS Office no problem.
I cannot share the DBF file - it contains confidential data.
Two things... just because its a .DBF file extension might night mean its a Dbase IV file. It might actually be that of Visual Foxpro. That said, I would look into downloading and installing the Visual Foxpro OleDB driver from Microsoft download. Next, the OleDbConnection is pointing to the path that has the actual tables (you already have that).
The query itself, shouldn't care about the extension, so I would change your call to get just then name via "Path.GetFileNameWithoutExtension"
It might be a combination of the two.
Connection string for VFP provider
"Provider=VFPOLEDB.1;Data Source=" + FullPathToDatabase
This is not the exact answer but it will help you to find the issue.
Try to give an inline connection string and select query to make sure problem is not with building those. Catch the exception and check the details of it.
OleDbConnection con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\folder;Extended Properties=dBASE IV;User ID=;Password=;"); // give your path directly
try
{
con.Open();
OleDbDataAdapter da = new OleDbDataAdapter("select * from tblCustomers.DBF", con); // update this query with your table name
DataSet ds = new DataSet();
da.Fill(ds);
con.Close();
int i = ds.Tables[0].Rows.Count;
return true;
}
catch(Exception e)
{
var error = e.ToString();
// check error details
return false;
}

How to read Excel file in c# by connection string?

How to read the excel file and show its data in grid view ? I tried the ODBC provider its working but, it is happening win "Dns=EXCELF", how it will possible with connection sring ? I generate my Excel sheet connection string as :
Provider=MSDASQL.1;Persist Security Info=False;User ID=admin;Data Source=Excel Files;Initial Catalog=D:\Parallelminds\Tryouts\sample.xlsx
Is that wrong ? please guide me. which connection string i have to give there...?
It varies somewhat by version of Excel, but if this is pre-2007, you can find what you need here: http://connectionstrings.com/excel
Otherwise, browse http://connectionstrings.com/. It's there somewhere, I promise :).
public string BuildExcelConnectionString(string Filename, bool FirstRowContainsHeaders){
return string.Format("Provider=Microsoft.Jet.OLEDB.4.0;
Data Source='{0}';Extended Properties=\"Excel 8.0;HDR={1};\"",
Filename.Replace("'", "''"),FirstRowContainsHeaders ? "Yes" : "No");
}
public string BuildExcel2007ConnectionString(string Filename, bool FirstRowContainsHeaders){
return string.Format("Provider=Microsoft.ACE.OLEDB.12.0;
Data Source={0};Extended Properties=\"Excel 12.0;HDR={1}\";",
Filename.Replace("'", "''"),FirstRowContainsHeaders ? "Yes" : "No");
}
private void ReadExcelFile(){
string connStr = BuildExcel2007ConnectionString(#"C:\Data\Spreadsheet.xlsx", true);
string query = #"Select * From [Sheet1$] Where Row = 2";
System.Data.OleDb.OleDbConnection conn = new System.Data.OleDb.OleDbConnection(connStr);
conn.Open();
System.Data.OleDb.OleDbCommand cmd = new System.Data.OleDb.OleDbCommand(query, conn);
System.Data.OleDb.OleDbDataReader dr = cmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(dr);
dr.Close();
conn.Close();
}
This Excel Data Provider is very handy. I recently used it on one of my client's websites with a few minor customizations. If you look through the code you should be able to get a solid idea of how to query Excel from C#.
Just a warning: if Excel is not installed on the deployment machine then you will be restricted to parsing standard XLS files (Office thru 2003), and will not be able to read XLSX (Office 2007).

Categories

Resources