SQL Server table export to Excel issue - c#

I am using 64-bit Windows Server 2008 with SQL Server 2008. And Using VS2008 + C# + .Net 2.0 + IIS 7.0 + ASP.Net. When executing the following statement, I met with the following error (the error occurs when accessing an aspx page), I am not sure whether it is 64-bit system specific issue?
Sys.WebForms.PageRequestManagerServerErrorException: unregistered OLE DB access interface "Microsoft.Jet.OLEDB.4.0"
StringBuilder sb = new StringBuilder();
sb.AppendLine("select * from OPENROWSET('MICROSOFT.JET.OLEDB.4.0','Excel 8.0;HDR=YES;DATABASE=" + s_path.Trim() + "',sheet1$) where name is not null"); //e:\\test1.xls
DataSet ds = SqlUtil.ExecuteDataset(Database.StrConn, CommandType.Text, sb.ToString());
if (ds.Tables[0].Rows.Count > 0)
{
GridView_Tlinkmans.DataSource = ds;
GridView_Tlinkmans.DataBind();
}

You have one or 2 issues:
You are querying OPENROWSET in SQL Server and you have x64 SQL Server, you may need the MDAC to bridge SQL Server to ODBC/OLEDB. However, this says it is part of the OS for Win 2008+. I've had to install on Win 2003
Then you probably need this which is the closest to JET I know of: Microsoft Access Database Engine 2010 Redistributable
YMMV

Related

C# - XLSX to SQL Server - OpenRecordSet not working in C# but works in MS SQL Server Management Studio

The following script works within a SQL Server 2014 Management Studio in a Stored Procedure but not when I call the stored proc via a C# app .NET Framework 4.8.
SQL Code:
create proc getData
as
Insert INTO tmpLeaveImport ([CarName], Year, Make , Model)
SELECT * FROM OPENROWSET('Microsoft.ACE.OLEDB.15.0',
'Excel 12.0;Database=E:\Cars\Cars.xlsx',
'SELECT * FROM [Car Report$]')
From C# I get the following error:
System.Data.SqlClient.SqlException: 'Cannot initialize the data source
object of OLE DB provider "Microsoft.ACE.OLEDB.15.0" for linked server
"(null)". OLE DB provider "Microsoft.ACE.OLEDB.15.0" for linked server
"(null)" returned message "Unspecified error".'
When this code is executed in C#:
//Tried the conn strign with Integrated Security=yes and SSPI
string ConnString = #"Data Sournce=MySQLServerDB;Initial Catalog=DBName;Integrated Security=true;";
using (SqlConnection conn = new SqlConnection(ConnString))
{
using (SqlCommand cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "getData";
cmd.CommandType = CommandType.StoredProcedure;
cmd.ExecuteNonQuery();
}
conn.Open();
}
Short Version
According to this possibly duplicate question the Excel file may be open. Or this could be a more serious error.
Don't use OPENROWSET to import Excel data into SQL Server. Use a library like ExcelDataReader to read it without using the Access Engine and insert it to the target table with SqlBulkCopy. You'll avoid a lot of pain.
using (var stream = File.Open(filePath, FileMode.Open, FileAccess.Read))
{
using (var reader = ExcelReaderFactory.CreateReader(stream))
{
using (var bcp = new SqlBulkCopy(connString))
{
bcp.DestinationTableName ="SomeTable";
bcp.WriteToServer(reader);
}
}
}
Long Version
In both cases, the stored procedure runs on SQL Server, not on the client. SSMS is just another client as far as SQL Server is concerned. Assuming the same server is used in both cases, what's different is that the account that executes the stored procedure is different in each case.
With SSMS, it's the developer's account which quite often has sysadmin privileges on the server. With C#, the account may be the end user's, or the application pool account that runs a web site, which has very restricted privileges. SQL Server's default service account is a restricted account too.
This matters because the Access Engine is a COM component. To use it, applications need to look it up in the registry, which requires its own permissions. If you search SO for the error you got you'll see questions where the choice of service account affected whether Access Engine can be used or not. In other cases, the file was open.
Another potential problem is that ACE must target the same architecture as any previous Office components installed on a machine. If you have a x86 Office application, you can only install the x86 version of ACE. That's because you can't use COM component created for one architecture from a process that targets another one.
This also means you can't use an x86 ACE in a x64 installation of SQL Server, which is the most common installation option in the last 10+ years.

MS Sync Framework and SQL Server Compact

I develop a Windows C# application which can work in Online and Offline mode.
When in Online mode it connects to a SQL Server. In Offline mode it connects to a local DB.
I use the Microsoft Sync Framework 2.1 to sync the 2 databases on demand.
Until now I used a LocalDB instance of SQL Server as the local database. But it is a pain to setup the system automatically during the installation process of my application. So I tought to use SQL Server Compact 3.5 or 4.0 which is very easy to distribute (comes in a single file).
But I cannot get it to even compile the provisioning code of the Compact DB:
DbSyncScopeDescription scopeDesc = new DbSyncScopeDescription("MyScope");
SqlCeConnection clientConn = new SqlCeConnection(OfflineConnectionString);
var clientProvision = new SqlCeSyncScopeProvisioning(clientConn, scopeDesc);
clientProvision.Apply();
which I used before (without the Ce classes) but SqlCeSyncScopeProvisioning cannot be resolved.
Something is terribly wrong here.
How can I sync my CompactDB to distribute this as my local database?
First ensure, you have successfully installed the sdk?
After this, make sure you have added the following references:
Microsoft.Synchronization.Data.dll,
Microsoft.Synchronization.Data.Server.dll
Microsoft.Synchronization.Data.SqlServer.dll
Microsoft.Synchronization.Data.SqlServerCe.dll
Also in my case it worked with adding
System.Data.SqlServerCe - 4.0
EDIT
Against your comment, this is only working if you use SQL Server CE 4.
I've tried it now with SQL Server CE 3.5 and indeed I could reproduce your issue.
Switching to SQL Server CE 4.0 fixed it.
ExampleTable 4.0
TestCode
var scopeDesc = new DbSyncScopeDescription("MyScope");
var tbl = new DbSyncTableDescription("TestTable");
var pkColumn = new DbSyncColumnDescription("Id", "int");
pkColumn.IsPrimaryKey = true;
tbl.Columns.Add(pkColumn);
tbl.Columns.Add(new DbSyncColumnDescription("Name", "nvarchar(254)"));
scopeDesc.Tables.Add(tbl);
var clientConn = new SqlCeConnection(#"Data Source=test.sdf;Persist Security Info=False;");
var clientProvision = new SqlCeSyncScopeProvisioning(clientConn, scopeDesc);
clientProvision.Apply();
Result
Everything compiles nicely. After following the above steps, you should be able to easily migrate your code to SQL Server CE

Microsoft Search Server or Microsoft Search Service in ASP.NET

I use ASP.NET 4.6.1 in Windows Server 2008 r2 using Indexing Server.
I use Microsoft OLE DB Provider for Microsoft Indexing Service, same Provider MSIDXS
Now, I want use Windows Server 2012 r2.
Indexing Service is no longer supported as of Windows XP and is
unavailable for use as of Windows 8. Instead, use Windows Search for
client side search and Microsoft Search Server Express for server side
search.
How use using Microsoft Search in ASP.NET?
I'm confused: I use Windows Search Server or Windows Search Service ?
Which OLE DB provider is required ?
How install Windows Search Server ?
How install Windows Search Service ? (maybe feature in Windows 2012 R2)
Downloading and installing Windows Search Server does not install the
OLE DB provider. Neither does installing the Windows SDK. The provider
is installed when the Windows Search Service is installed.
On Win7/8 desktop OS, this is installed be default (I believe). On
server Windows Server 2012, you have to enable the feature.
My code using Indexing Server in Windows 2008 R2 + ASP.NET:
// Catalog Name
string strCatalog = txtNombreCatalogo.Text;
string strQuery = "";
strQuery = "Select DocTitle,Filename,Size,PATH,URL";
strQuery += ", DocAuthor, vpath, Write, Rank, Create, Characterization, DocCategory";
strQuery += " from Scope() where FREETEXT('" + txtNombreFichero.Text + "')";
// txtNombreFichero.Text is the word that you type in the text box to query by using Indexing Service.
string connstring = "Provider=MSIDXS;Integrated Security .='';Data Source=" + strCatalog;
//connstring = "Provider=MSIDXS.1;Integrated Security .='';Data Source=" + strCatalog;
var conn = new System.Data.OleDb.OleDbConnection(connstring);
conn.Open();
var cmd = new System.Data.OleDb.OleDbDataAdapter(strQuery, conn);
var testDataSet = new System.Data.DataSet();
cmd.Fill(testDataSet, "SearchResults");
DataView source = new DataView(testDataSet.Tables[0]);
dgResultados.DataSource = source;
dgResultados.DataBind();
I'm confused: I use Windows Search Server or Windows Search Service ?
You use Indexing search(https://msdn.microsoft.com/en-us/library/ee805985(v=vs.85).aspx).
Which OLE DB provider is required ?
For use Windows Search Service use "Provider=Search.CollatorDSO;Extended Properties='Application=Windows'; Data Source=(local);"
How install Windows Search Server ?
For use Windows Search Server you should download and install Microsoft Search Server(based on sharepoint) https://www.microsoft.com/en-us/download/details.aspx?id=18914.

replacing data access strategy from SQL Server to Access MDB file in C#

I created a small accounting application a while back. It uses SQL Server 2008 as backend data store. Now I realize that SQL Server is too much for such a
small program PLUS it is not very much portable. I mean I want to have this application on my USB stick for easy access anywhere, and SQL Server will not be
available everywhere. So now I want to replace the data store from SQL Server to something portable i.e. MS Access MDB file.
1- Is it a good option or should I use SQL Server express edition?
2- I don't have experience using SQL Express edition. If I use it, would it be needed on any machine where I intend to run my application?
2- What changes should I make in the code to make it compatioble with MDF files (or SQL Express)?
As I said it is quite simple program, it uses connected model to fetch and insert data currently. For example
void bindGrid()
{
try
{
using (SqlConnection con = new SqlConnection(ConnectionString))
{
DataSet set = new DataSet();
SqlDataAdapter da = new SqlDataAdapter();
SqlCommand selectCommand = new SqlCommand("SELECT * FROM Categories ORDER BY name", con);
da.SelectCommand = selectCommand;
da.Fill(set);
this.grdCategories.DataSource = set.Tables[0];
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Rather than using Access, I would use LocalDB. It should require very few if any changes to your code other than the connection string.
http://blogs.msdn.com/b/sqlexpress/archive/2011/07/12/introducing-localdb-a-better-sql-express.aspx
LocalDB is created specifically for developers. It is very easy to install and requires no management, yet it offers the same T-SQL language, programming surface and client-side providers as the regular SQL Server Express. In effect the developers that target SQL Server no longer have to install and manage a full instance of SQL Server Express on their laptops and other development machines. Moreover, if the simplicity (and limitations) of LocalDB fit the needs of the target application environment, developers can continue using it in production, as LocalDB makes a pretty good embedded database too.
I would recommend SQL CE for small projects.
LocalDB vs SQL Server Compact
There are significant differences between LocalDB and SQL Server Compact:
Execution mode: SQL Server Compact is an in-proc DLL, while LocalDB runs as a separate process.
Disk usage: all SQL Server Compact binaries amount to some 4MBs, while LocalDB installation takes 140MBs.
Features: SQL Server Compact offers core RDBMS functionality like querying, while LocalDB provides a much richer set of features, including Stored Procedures, Geometry and Geography data types, etc.

Find out in C# if my SQL Server instance supports snapshots?

I want to write c# code to make a snapshot-backup if available. This is supported since SQL Server version 2005 but only in Enterprise edition but not in Express or Standard edition.
My question: how to find out in C# if the connected server supports snapshot backup (is Enterprise Edition 2005 or newer or some kind of "hasFeature(...))?
My current solution puts a try catch around the following code.
sqlCommand.CommandText = String.Format("CREATE DATABASE {0} ON " +
(NAME = {1}, FILENAME = \"{2}\" ) AS SNAPSHOT OF {1}",
databaseBackupName,
databaseName,
filenameOfDatabseBackup);
sqlCommand.ExecuteNonQuery();
If I catch a SqlException I assume there is no support on the connected server.
But maybe there could be other reasons to fail although the database supports snapshots (i.e. something is locked, connection is broken, ...)
The ideal solution would be some sqlCommand.ExecuteNonQuery() to find out if the feature is supported.
The second best is if I had to include some extra dll that can find it (?sqldmo?) but this would create an additional dependency to the project.
The third best would be some kind of exception handling.
You could certainly do something like this:
SELECT
SERVERPROPERTY('productversion') as 'Product Version',
SERVERPROPERTY('engineedition') as 'Engine Edition'
The Product Version will give you a string like this: 10.50.1600.1. SQL Server 2005 is version 9, so anything that starts with 9., 09. or 10., 11. will be fine.
The Engine Edition gives you an INT (1 = personal/MSDE/Express, 2 = standard, 3 = enterprise/developer).

Categories