SQL Sever 2014 Query Notifications in C++ with ADO.NET libraries - c#

I have a C++ application that has to react to status changes that are kept in an SQL database. They have to react in real-time, and currently this is done by polling. However the real-time response time I need is overloading the database.
I have read about Query Notifications introduced in SQL Server 2005, but in truth I don't really understand the different SQL connection methods available. Currently I use ADO.NET to faciliate database communication, but the only sample code I have found for doing Query Notifications of this nature is in C# and VB. Not to mention that I am struggling to understand the concept. Here is a sample of how I currently run SQL with ADO.NET.
hr = link.CreateInstance(__uuidof(Connection) );
if (link) { // Execute the query on the open connection using existing command object
pCommand.CreateInstance(__uuidof(Command));
pCommand->ActiveConnection = link;
pCommand->CommandType = ado20CommandType;
pCommand->CommandText = strQuery.GetBuffer(0);
pCommand->PutPrepared(true);
pCommand->NamedParameters = true;
if (pRecordSet = pCommand->Execute(&vRecordsAffected,NULL,NULL)) { // Execute the final query and set object-level recordset object
lRecordsAffected = vRecordsAffected.lVal;
_RecordsetPtr pfuRecordSet = link->Execute(_T("SELECT ##IDENTITY as pmIDENT;"),NULL,adCmdText);
CString strID = pfuRecordSet->GetFields()->GetItem(COleVariant("pmIDENT"))->Value.bstrVal;
int nID = atoi(strID);
if (nID > 0) {
nLastInsertedID = nID;
}
return true;
}
I was wondering if someone could provide me with resources and/or sample code that would help me set this up in C++? Thanks in advance.

The fastest way to get data out of a SQL Server database is using the SqlDataReader, which is forward-only, read-only.
Take a look at this C++ code and give that a try.
http://tinyurl.com/m6u9jh7

Related

C# can't get datas from stored procedure with opendatasource and Microsoft.ACE.OLEDB.16.0

I have a strange issues reading data from an Eexcel file.
I made a query in SQL Server with OPENDATASOURCE:
SELECT COMPETENZA, [CODICE CLEINTE], [RAGIONE SOCIALE], MODELLO, VARIANTE,
TIPOLOGIA, ESSENZA, FINITURA, TAPPEZZERIA, COMMESSA, ROUND([% MOL SU RICAVI NETTI] * 100,2) as MARGINE
FROM OPENDATASOURCE('Microsoft.ACE.OLEDB.16.0',
'Data Source=K:\UTENTI\SAMUELE\temp id commesse\ID Commesse produzione.xls;Extended Properties=EXCEL 12.0')...['Consuntivi produzione$']
WHERE MODELLO IS NOT NULL AND [% MOL SU RICAVI NETTI] IS NOT NULL
If I execute this query in a stored procedure, it works fine.
But when I execute from C# by an HttpGet I get this issues:
System.Data.SqlClient.SqlException (0x80131904): Cannot initialize the data source object of OLE DB provider "Microsoft.ACE.OLEDB.16.0" for linked server "(null)".
This is my C# code:
[HttpGet]
public async Task<JsonResult> GetMarginiCommessaListJSON()
{
var yourdata = GetMarginiCommessaList();
return Json(new { data = yourdata });
}
public List<MarginiCommessa> GetMarginiCommessaList()
{
SqlDataReader reader;
SqlConnection sqlConn = new SqlConnection(_configuration["dbConnectionString"]);
string sqlCmdStr = "MARGINI_COMMESSE";
SqlCommand sqlCmd = new SqlCommand(sqlCmdStr, sqlConn);
sqlCmd.CommandType = CommandType.StoredProcedure;
List<MarginiCommessa> allestList = new List<MarginiCommessa>();
try
{
using (sqlConn)
{
sqlConn.Open();
reader = sqlCmd.ExecuteReader();
while (reader.Read())
{
allestList.Add(new MarginiCommessa
{
anno = reader.GetValue(0).ToString(),
codCli = reader.GetValue(1).ToString(),
nomCli = reader.GetValue(2).ToString(),
modello = reader.GetValue(3).ToString(),
variante = reader.GetValue(4).ToString(),
tipologia = reader.GetValue(5).ToString(),
essenza = reader.GetValue(6).ToString(),
finitura = reader.GetValue(7).ToString(),
tapezzeria = reader.GetValue(8).ToString(),
commessa_qta = reader.GetValue(9).ToString(),
margine = reader.GetValue(10).ToString()
});
}
reader.Close();
sqlConn.Close();
}
}
catch (Exception e)
{
System.IO.File.WriteAllText(GlobalVariables.errorFolderLocation + "GetMarginiCommessaListJSON.txt", e.ToString());
}
return allestList;
}
And this is my Stored procedure:
ALTER PROCEDURE [dbo].[MARGINI_COMMESSE]
AS
BEGIN
SET NOCOUNT ON;
SELECT COMPETENZA, [CODICE CLEINTE], [RAGIONE SOCIALE], MODELLO, VARIANTE,
TIPOLOGIA, ESSENZA, FINITURA, TAPPEZZERIA, COMMESSA, ROUND([% MOL SU RICAVI NETTI] * 100,2) as MARGINE
FROM OPENDATASOURCE('Microsoft.ACE.OLEDB.16.0',
'Data Source=K:\UTENTI\SAMUELE\temp id commesse/ID Commesse produzione.xls;Extended Properties=EXCEL 12.0')...['Consuntivi produzione$']
WHERE MODELLO IS NOT NULL AND [% MOL SU RICAVI NETTI] IS NOT NULL
END
I really don't understand why in SQL Server it works fine and in C# not.
How can I fix this?
OP #1:
I have a strange issues reading datas from an excel file. I made a query in mssql with OPENDATASOURCE: If i execute this query in a stored procedure, it works fine.
OP #2:
But when i execute from c# by an HttpGet i get this issues:
Firstly, that's an apples and oranges comparison. On one hand you are using MySQL and the other SQL Server. The latter case you also have a web app using ADO.NET in order to reach the stored proc.
Now I can't vouch for MySQL or whatever OPENDATASOURCE is doing in both occasions but one thing is certain - you appear to be using ACE OLEDB "Jet" in a server setting which may be the cause of your issues. Crashes aside, using ACE might have licensing issues. See below.
Microsoft (my emphasis):
Although such programmatic development can be implemented on a client system with relative ease, a number of complications can occur if Automation takes place from server-side code such as Microsoft Active Server Pages (ASP), ASP.NET, DCOM, or a Windows NT service.
NOTE: In this context, the Access Database Engine Redistributable and Access Runtime are considered Microsoft Office components.
...and:
Developers who try to use Office in a server-side solution need to be aware of five major areas in which Office behaves differently than anticipated because of the environment.
...and most importantly (my emphasis):
Besides the technical problems, you must also consider licensing issues. Current licensing guidelines prevent Office applications from being used on a server to service client requests, unless those clients themselves have licensed copies of Office. Using server-side Automation to provide Office functionality to unlicensed workstations is not covered by the End User License Agreement (EULA).
Conclusion
So even if you fix the technical issue, be mindful of that last pointer.
See also
Considerations for server-side Automation of Office, Microsoft

SQL Slow in code not SSMS

I am running into issues working with a very large table from C# .Net 4.0.
For reference the table has ~120 Million rows.
I can't do even a simple query like
SELECT TOP(50) *
FROM TableName
WHERE CreatedOn < '2015-06-01';
From code it will timeout (Default setting - 15 seconds I believe), but in SSMS it is instant.
There is an index on the column in the WHERE clause. I have also tried explicitly casting the string to a DateTime, and using a DateTime parameter instead of a literal value.
I tried a different query that filters by the PK (bigint, identity, clustered index) If I do something like "Where TableRowID = 1" it works fine from code, but if I try to use "<" or "<=" instead it will timeout (returns instantly in SSMS), regardless of how many rows are turned.
The execution plans are very simple and are exactly the same.
I have tried changing ARITHABORT but that has had no effect.
I tried having the Application connect with my own account (SSPI) instead of its own credentials with no effect.
I have been researching this issue for a few days, but everything I have found blames different execution plans.
Does anyone have any idea what could be causing this issue?
The .Net code looks like this:
private DataSet ExecuteQuery(string query, string db, List<SqlParameter> parms = null)
{
string connectionString = ConfigurationManager.ConnectionStrings[db].ToString();
SqlConnection con = new SqlConnection(connectionString.Trim());
SqlDataAdapter sqlDataAdapter = new SqlDataAdapter();
try
{
con.Open();
DataSet ds = new DataSet();
sqlDataAdapter.SelectCommand = new SqlCommand(query, con);
sqlDataAdapter.SelectCommand.CommandType = CommandType.Text;
if (parms != null)
{
foreach (SqlParameter p in parms)
{
sqlDataAdapter.SelectCommand.Parameters.Add(p);
}
}
sqlDataAdapter.Fill(ds);
if (ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
return ds;
}
return null;
}
finally
{
if (sqlDataAdapter != null)
sqlDataAdapter.Dispose();
if (con != null)
con.Dispose();
}
}
The error message I get in .Net is the standard timeout message:
Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
Here are my experience when dealing the issues.
Very C# sql code passed to sql server is
SELECT TOP(50) *
FROM TableName
WHERE CreatedOn < '2015-06-01'
Make sure the criteria. If it takes "instant time" to retrieve records on SSMS, the sql statement and db optimization is ok.
As other people have pointed out, you should post your C# codes and see what happens. There could be other issues. Could that be network? Could that be web.config? Do you call directly from C# code? Do you call via web service?
when you said time out? Does it time out at the time you execute the query. There is very little information you provide. Do you use third party routines (such as written by vendor or your company) to execute queries? If it possible, put the break point at the code that execute sql statement. What I mean is dig all the way to native codes, and put the break codes.
120 million records. Looks like the database has be optimized if it runs very fast on SSMS. I would take look outside SQL server.
good luck
My first step there would be to look at what your code is sending to the sql server. I'd begin by running the sql profiler. if you're not familiar with it. Here is a link on how to use it.
https://www.mssqltips.com/sqlservertip/2040/use-sql-server-profiler-to-trace-database-calls-from-third-party-applications/
After this you may want to look into network traffic times between the 2 servers.
Then look at IIS and see how it's setup. Could be a setting is wrong.
Check the error logs and see if you have any errors as well.
When you execute code in SSMS, the system is setting some default values on your connection. Specifically, look at Tools --> Options --> Query Execution --> Sql Server --> Advanced (and also ANSI). These statements are executed on your behalf when you open a new query window.
When you create your connection object in C#, are you setting these same options? If you don't explicitly set them here, you are taking the default values as defined in the actual SQL Server instance. In SSMS, you can get this by viewing the properties of the server instance and choosing the Connections page. This shows the default connection options.
You can also get this information without using the UI (you can do this in a separate application that uses the same connection string, for example). This article on MSSQLTips should guide you in the right direction.

How to store and retrieve .pdf, .exe file in SQL Server 2008

I am currently working on a Windows Forms application (C#, VS 2010) and I need to create functionality that enables users to upload .pdf, .exe files into a SQL Server 2008 database and download them back.
The problem that I have is that the file downloaded from the database is always corrupted (except .txt file) even though they are the same size. And I have used varbinary(MAX) as the file type to store the data in the database.
Can anyone show me some example code for how to do this?
PS: I have researched for more than a week, but still cannot find a solution to my problem, can anyone please help? Any answer will be highly appreciated.
In the below example there are a few assumptions made:
I'm using Dapper for the database access. It extends any IDbConnection object.
I have a table in the database that has a definition as such CREATE TABLE Data (Id INT IDENTITY(1, 1) PRIMARY KEY, Data VARBINARY(MAX)).
Here is the documentation for ReadAllBytes
So, obviously since you didn't provide anything surrounding your table structure you're going to have to change this code to meet you needs, but it will get you started.
Writing It
this.connection.Open();
try
{
var parameters = new
{
Data = File.ReadAllBytes(...);
};
return connection.Execute("INSERT INTO Data (Data) VALUES (#Data)", parameters);
}
finally
{
this.connection.Close();
}
Reading It
this.connection.Open();
try
{
var parameters = new { Id = 1 };
return connection.Query(
"SELECT Data FROM dbo.Data WHERE Id = #Id", parameters)
.Select(q => q.Data as byte[])
.Single();
}
finally
{
this.connection.Close();
}

Beginner requests Help with Mysql and C#

I'm trying to build a program that uses a C# to work with a MySQL DB. I get the C# syntax, and can write the language, but I don't have much experience with the libraries, and I feel a bit lost.
Could someone post examples of how a program would be built (in technical terms, syntax would be nice, but pseudo code is fine, too)?
I understand the theory of how it works, but need a hands on approach to it.
Thank you.
EDIT
I forgot to add that I want to learn how to do it with the .NET v.2.0 framework / VS2005 / MySQL v5.0 combination.
EDIT # 2
2.0 .NET will only be supported. =)
Here is tutorial for Entity Framework + MySQL.
There are lots of other ways to operate with DB, depending on what you need:
If you need execute raw sql queries against DB - use OdbcConnection + OdbcCommand
Need to manipulate items in DB as objects - use ORM (EntityFramework, NHibernate, Linq2Sql)
Like old-style DB interop? - DataSets is your choice.
I really like EF. Easy thing to start with.
PS: And before mixing UI and DB-interop, please read about Separation of concerns. MVC is interesting to read about too. About "libraries": create another project in your solution and add DB-interop logics there. Don't mix it in one assembly, because when your project becomes bigger than "Hello DataBase!" application it will create a big mess in code and logics, really.
UPDATE:
Using VS2005 and .net 2.0 is mysterious idea, really. Lots of tools and assemblies where made since 2.0 release. Linq, Orm-s, etc. Live without them is hard and all the benefits of C# are lost. I highly recommend to use latest techniques, if there is no strict reasons to use 2.0.
If using SqlServer - ObdcCommand and OdbcConnection can be replaced to SqlCommand and SqlConnection. (thanks #Abe Miessler comment)
Here is an example swiped from MSDN:
public void InsertRow(string connectionString, string insertSQL)
{
using (OdbcConnection connection =
new OdbcConnection(connectionString))
{
// The insertSQL string contains a SQL statement that
// inserts a new row in the source table.
OdbcCommand command = new OdbcCommand(insertSQL, connection);
// Open the connection and execute the insert command.
try
{
connection.Open();
command.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
// The connection is automatically closed when the
// code exits the using block.
}
}
If you want to read records in a DB, look at this example:
public static void ReadData(string connectionString)
{
string queryString = "SELECT DISTINCT CustomerID FROM Orders";
using (OdbcConnection connection = new OdbcConnection(connectionString))
{
OdbcCommand command = new OdbcCommand(queryString, connection);
connection.Open();
// Execute the DataReader and access the data.
OdbcDataReader reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine("CustomerID={0}", reader[0]);
}
// Call Close when done reading.
reader.Close();
}
}
FYI i am just copy/pasting these directly from MSDN. I highly recommend reading over their documentation and looking at their examples if you are just getting started.
http://msdn.microsoft.com/en-us/library/system.data.odbc.odbcdatareader.aspx
Here is a blog post getting you started with MySql and C#.
http://blog.bobcravens.com/2010/06/the-repository-pattern-with-linq-to-fluent-nhibernate-and-mysql/
Hope that gets you started.
Bob

Is there a way to set the DB as Single User Mode in C#?

I have a WPF app that updates my database from an in-code entity model. There may be instances that it updates the DB while there are users connected and I would like to put it in Single-User-Mode to avoid errors.
I would also like to avoid using sql. I am aware that I can run sql using:
DataContext.ExecuteCommand("ALTER DATABASE...")
I would rather use a command in a C# library to do this but I dont know where to look.
Is there a way to set the DB to SUM without using SQL?
So I used the SMO server objects like this:
Server server = GetServer();
if (server != null)
{
Database db = server.Databases[Settings.Instance.GetSetting("Database", "MyDB")];
if (db != null)
{
server.KillAllProcesses(db.Name);
db.DatabaseOptions.UserAccess = DatabaseUserAccess.Single;
db.Alter(TerminationClause.RollbackTransactionsImmediately);
The problem was that this opened a different connection than my datacontext thus kicking myself off and not letting me access the DB. In the end I had to revert to using SQL.
You can use SQLDMO to manage SQL Server objects.
http://msdn.microsoft.com/en-us/library/ms162169.aspx

Categories

Resources