I'm using Signalr with SqlDependency. My code works and it shows me realtime results like I wanted. But the issue is it is working my newly created database. If I change the database to old one the SqlDependency stops work and not getting the change detection on my database table.
Below is my code:
#region SignalRMethods
[System.Web.Script.Services.ScriptMethod()]
[System.Web.Services.WebMethod(EnableSession = true)]
public GlobalApplicationError[] GetErrorsList()
{
var cs = "Data Source=.;Initial Catalog=NotifyDB;Integrated Security=True";
using (var connection = new SqlConnection(cs))
{
connection.Open();
SqlDependency.Start(cs);
using (SqlCommand command = new SqlCommand(#"SELECT [Form_Name],[Message],[Prepared_By_Date] FROM [GlobalApplicationError]", connection))
{
// Make sure the command object does not already have
// a notification object associated with it.
SqlDependency dependency = new SqlDependency(command);
dependency.OnChange += new OnChangeEventHandler(dependency_OnChange);
if (connection.State == ConnectionState.Closed)
connection.Open();
using (var reader = command.ExecuteReader())
return reader.Cast<IDataRecord>()
.Select(x => new GlobalApplicationError()
{
Form_Name = x["Form_Name"].ToString(),
Message = x["Message"].ToString(),
Prepared_By_Date = Convert.ToDateTime(x["Prepared_By_Date"])
}).ToList().ToArray();
}
}
}
private static void dependency_OnChange(object sender, SqlNotificationEventArgs e)
{
MyHub.Show();
}
#endregion
Above code perfectly works on database NotifyDB but not on my existing one which is eprocure if I change the database in my connection string. As I'm using the asmx web service so I always update the reference of my web service. Plus I've enable_broker set to true on both databases.
Database screen shots:
NotifyDB
eprocure
output
Kindly let me know what I'm doing wrong in my code. Thanks in advance.
Let windup this. After some brainstorming on internet I successfully found my answer.
I've Checked my database sys.transmission_queue using below query:
select * from sys.transmission_queue
As most likely our notification(s) will be there, retained because they cannot be delivered. The transmission_status have an explanation why is this happening.
I found that there is below error:
Error: 15517, State: 1. Cannot execute as the database principal because the principal "dbo" does not exist
Google it and found the below useful link:
Troubleshooting SQL Server Error 15517
after that I run the below query which is briefly defined in above link
EXEC sp_MSForEachDB
'SELECT ''?'' AS ''DBName'', sp.name AS ''dbo_login'', o.name AS ''sysdb_login''
FROM ?.sys.database_principals dp
LEFT JOIN master.sys.server_principals sp
ON dp.sid = sp.sid
LEFT JOIN master.sys.databases d
ON DB_ID(''?'') = d.database_id
LEFT JOIN master.sys.server_principals o
ON d.owner_sid = o.sid
WHERE dp.name = ''dbo'';';
By doing this, I found several databases that sys.databases said had an owner. However, when I checked it from the database's sys.database_principals, the SID didn't match up for dbo. The column I had for dbo_login came back NULL. That was a clear sign of the issue. There is also the possibility you will see a mismatch between dbo_login and sysdb_login. It appears that as long as dbo_login matches a legitimate login, the error is not generated. I found that on some DBs on one of my servers. While it's not causing a problem now, I'll be looking to correct the mismatch.
Correcting the Error:
The easiest way to correct the error is to use ALTER AUTHORIZATION on the databases which have the NULL login match for dbo. It's as simple as:
ALTER AUTHORIZATION ON DATABASE::eprocure TO sa;
So finally. I got what I want and my SQL Dependency is working fine. This is all from my end. Thanks you help me on this post. I appreciate for your precious time. Happy Coding.
Please make sure Query Notifications & Service broker are enabled and permissions for the IIS identify are granted.
Steps to enable : https://techbrij.com/database-change-notifications-asp-net-signalr-sqldependency
To check service broker is enabled execute the below statement
SELECT name, is_broker_enabled FROM sys.databases
To enable service broker
ALTER DATABASE <<DatabaseName>> SET ENABLE_BROKER
To grant permission to a user
GRANT SUBSCRIBE QUERY NOTIFICATIONS TO “<<USERIDENTITY>”
Related
Assume we have a stored procedure like so
CREATE PROCEDURE CopyValue(IN src INT, OUT dest INT)
BEGIN
SET dest = src;
END
I want to call this from a .net app (assume connection etc created successfully)
var sql = "call CopyValue(100, #destValue); select #destValue as Results;";
The string in the above statement works perfectly well when called in MySql Workbench.
However this - obviously - fails with "MySqlException: Parameter '#destValue' must be defined" when executed on a MySqlCommand object in .net
How do I arrange this statement so I can capture an output parameter from an existing procedure?
NB: I'm running against MySql 5.6, which I can't upgrade at this time.
NB Calling the procedure directly with CommandType.StoredProcedure goes against company guidelines.
By default, user-defined variables aren't allowed in SQL statements by MySQL Connector/NET. You can relax this restriction by adding AllowUserVariables=true; to your connection string. No modifications to your SQL or how you're executing the MySqlCommand should be necessary.
For information about why this is the default, you can read the research on this MySqlConnector issue (which also has the same default behaviour, but a much better error message that will tell you how to solve the problem): https://github.com/mysql-net/MySqlConnector/issues/194
A colleague (who wishes to remain anonymous) has answered this perfectly. Essentially put backticks ` after the # and at the end of the variable name e.g.
#`MyParam`
A fully working example.
static void Main(string[] args)
{
using var con = new MySql.Data.MySqlClient.MySqlConnection("Data Source=localhost; User Id=...;Password=...;Initial Catalog=...");
con.Open();
using var cmd = con.CreateCommand();
cmd.CommandText = "call CopyValue2(100, #`v2`); select #`v2` as Results;";
using var reader = cmd.ExecuteReader();
if (reader.Read())
Console.WriteLine($"Copied Value {reader.GetInt64(0)}");
}
Thanks OG :)
I've created a Winforms app in C#. I do have both my Datasources listed as Datasets.
LOTSDataSet = Source Info
webbitdbdataset = Destination Dataset.
These are connected with LOTSConnectionString and WebbitConnectionString.
Anyway I have the code shown below that I am getting a connection error on, when I try to import data from LOTS to Webbit.
SqlConnection lotscon = new SqlConnection(PackChecker.Properties.Settings.Default["LOTSConnectionString"].ToString());
using (OleDbConnection con = new OleDbConnection(PackChecker.Properties.Settings.Default["WebbitConnectionString"].ToString()))
{
string strgetloc = #"INSERT INTO tblinstitution (
dispenseinstid, institutionname )
SELECT NEWinstitution.institutionid, NEWinstitution.institutionname
FROM NEWinstitution LEFT JOIN tblinstitution ON NEWinstitution.institutionid
= tblinstitution.dispenseinstid
WHERE (((tblinstitution.institutionid) Is Null));";
using (OleDbCommand cmd = new OleDbCommand(strgetloc, con))
{
lotscon.Open();
con.Open();
cmd.ExecuteNonQuery();
con.Close();
lotscon.Close();
}
}
Trying to "OPEN CONNECTION" for both connections was just something I tried.. I guess knowing it was going to fail, but I wanted to try before I asked on here.
The command is attached to the OLEDB connection to Webbit, thus I'm getting an exception based on 'cannot find LOTS server'
Prior to running the query I do run a connection checker, which opens both connections and "tries and catches" both connections to make sure they are valid connections.
Using Access the query does work, so I know the issue 100% is trying to open these connections to two databases!
Any direction would be appreciated.
Gangel
I am struggling with using ORACLE parameters via DAPPER. The error message received is "ORA-00942: table or view does not exist".
However the code works without the parameter, and I suspect that this is a simple Oracle parameter syntax issue. The code follows:
public List<ForecastData>GetByFiscalYear(string fiscalYear)
{
List<ForecastData> queryResults = new List<ForecastData>();
String sqlQuery = #"SELECT RES.FISCALYEAR year FROM RESOURCE_AVAILABILITY RES WHERE RES.FISCALYEAR = :p_fiscalYear";
using (var oraCon = new OracleConnection(System.Configuration.ConfigurationManager.ConnectionStrings["Oracle_HRZD"].ToString()))
{
oraCon.Open();
queryResults = oraCon.Query<ForecastData>(sqlQuery, new { p_fiscalYear = fiscalYear }).ToList();
}
return new List<ForecastData>(queryResults);
}
Any assistance will be greatly appreciated...
Usually, ORA-00942 is exactly what it says, it can't find the table/view (RESOURCE_AVAILABILITY) you are selecting from. So it's not in the schema for the user you log on as or the user has not been granted SELECT on the table/view if it's another schema.
But you say that if you remove WHERE RES.FISCAL_YEAR :p_fiscalyear, then it works. So it seems like you have select permissions on the table. Do you mean remove the whole where selection or have you tested enter a fixed string, as in WHERE RES.FISCAL_YEAR='2016'?
My other top tip is to run Wireshark and look at what really is sent to the database, usually you connect on port 1521 filter on that.
The answer was to use the fully-qualified database-object name, including the schema. Thanks for your assistance.
In my database, I have 2 schemas: [dbo] and [rch] ([rch] was selected as the name for our "archived" data so that those tables would not appear before the [dbo] tables).
I created a user for this table called rchuser in SQL Server Management Studio (SSMS):
Notice above that the user is added with rch listed as the Default Schema.
Notice above that this new user owns both db_owner and rch.
Let's say I have this SQL insert:
public static int AddRecord(object value, string sqlConnection)
{
int result = 0;
using (var conn = new System.Data.SqlClient.SqlConnection(sqlConnection))
{
conn.Open();
var sqlCmd =
"INSERT INTO Table1 ([Value], [Stamp]) " +
"VALUES (#Value, GETDATE()); ";
using (var cmd = new System.Data.SqlClient.SqlCommand(sqlCmd, conn))
{
cmd.Parameters.AddWithValue("#Value", value);
result = cmd.ExecuteNonQuery();
}
}
return result;
}
I passed that method a connection string using my rchuser credentials.
var conn = "Data Source=localhost;Initial Catalog=DatabaseN;User Id=rchuser;Password=password;"
There is no error, result is 1, but the new record is NOT in the corresponding table for my [rch] schema.
It is like the database is completely ignoring the fact that this user defaults to the [rch] schema.
I even tried logging into the SSMS database with rchuser to execute the command by hand. Again, no errors. The data went into [dbo].
How do I direct all database input to go to another schema?
If you have multiple schemas in a database, then my recommendation is to always explicitly specify which one you want. Aaron Bertrand has a good article on why you should do it, even if you only have one schema.
So modify your sql statement to be
INSERT INTO [rch].Table1...
and you will be all good.
I do note that this doesn't answer your title, but it does answer your question.
As to why your query isn't defaulting to the [rch] schema, I don't know. I replicated your setup in SQL Server 2008 R2, and when I run your original query then the inserts do go into the rch table as expected.
EDIT:
I did some Googling, and I suspect that your problem is caused by granting the sysadmin server role to the rchuser login. I modified mine to be an sa
, and now the inserts go into the [dbo] schema by default, even though rchuser has a default schema of [rch].
So, if you remove the sysadmin server role, it should start working as expected.
Have You tried to specifiy schema for table in Your query?
var sqlCmd =
"INSERT INTO rch.Table1 ([Value], [Stamp]) " +
"VALUES (#Value, GETDATE()); ";
I am inserting a SQL Database Backup and Recovery section into my program. I have been using MSDN Examples (tryed another and it wouldnt work).
MSDN Page - http://msdn.microsoft.com/en-us/library/ms162133.aspx
I have got the Backup file working, and have tested the file in Management Studio.
But I am having trouble with the Recovery of the file.
The code seems to be working, but the database in SQL Server is stuck in "Restoring..."
if (openFile.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
Server sqlServer = new Server();
Restore sqlRestore = new Restore();
sqlRestore.NoRecovery = true;
sqlRestore.Action = RestoreActionType.Database;
BackupDeviceItem deviceItem = new BackupDeviceItem(openFile.FileName, DeviceType.File);
sqlRestore.Devices.Add(deviceItem);
sqlRestore.Database = "firstRecoverTest";
sqlRestore.SqlRestore(sqlServer);
//Add the recovered database into the Entity Table
SqlCommand intoEntity = new SqlCommand("IF NOT EXISTS(SELECT entityName FROM Entitys WHERE entityName = 'firstRecoveryTest') INSERT INTO Entitys VALUES ('firstRecoveryTest');", sqlConnection);
sqlConnection.Open();
intoEntity.ExecuteNonQuery();
Database db = default(Database);
db = sqlServer.Databases["firstRecoverTest"];
db.RecoveryModel = (RecoveryModel)1;
db.AutoClose = true;
//db.Alter();
}
In the example there is a db.Alter(); function, but that throws an error that says "Alter failed for Database 'firstRecoverTest'".
Please let me know your thoughts
Thanks in advance
UPDATE
After inserting the "ReplaceDatabase = true;" there was no change in the end result.
Also stepping though the code line by line, shows that it is making it through.
The "db.Alter();" is just that placed at the end of the code (shown as comment). It is used in the creation of the backup and works without error.
InnerError shows this information when using db.Alter();
"ALTER DATABASE is not permitted while a database is in the Restoring state"
The interesting part is the SQL Log files. I am getting 3 Logs:
"Starting up database 'firstRecoverTest'."
"The database 'firstRecoverTest' is marked RESTORING and is in a state that does not allow recovery to be run."
"Database was restored: Database: firstRecoverTest, creation date(time): 2011/09/20(15:44:48), first LSN: 37:159:37, last LSN: 37:175:1, number of dump devices: 1, device information: (FILE=1, TYPE=DISK: {'C:\Users\Administrator\Desktop\installer_backup'}). Informational message. No user action required."
However, when I do a normal recover using SQL Management Studio there is 2 more log entrys saying
"Starting up database '[databaseName]'."
"Restore is complete on database '[databaseName]'. The database is now available"
I don't have enough reputation to post a small image of how it is in SQL Management Studio unfortunatly.
You should try either dropping the database or using sqlRestore.ReplaceDatabase = true;.
http://msdn.microsoft.com/en-us/library/microsoft.sqlserver.management.smo.restore.replacedatabase.aspx
If it looks like nothing is happening you can start the process in a seperate thread and wire up the events for notification of progress changes by using these.
sqlRestore.Complete += new ServerMessageEventHandler(completionEvent);
sqlRestore.PercentCompleteNotification = 10; // Call progress event every x percent change.
sqlRestore.PercentComplete += new PercentCompleteEventHandler(progressEvent);
If that doesn't work can you please post the Alter code that wasn't working. Also check SQL server logs and permissions.
UPDATED
Ok that update makes more sense. The reason is because you are setting sqlRestore.NoRecovery = true;. This has the effect that after the restore is done the DB is kept in a recovery state so you can restore an additional differential backup in addition to the full you just restored.
While it is in this state you will not be able to do anything more to the database. I would suggest that unless you require it you leave the default which is NoRecovery = false.
See http://msdn.microsoft.com/en-us/library/microsoft.sqlserver.management.smo.backuprestorebase.norecovery.aspx
Hope that helps.