C# Recovering Database stuck in 'Restoring...' - c#

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.

Related

Linq to SQL not saving to database on SubmitChanges()

I have a database with three tables in it. I created all the tables within Visual Studio. My C# code is connecting to the database using Linq to SQL. The table I am having problems with is not updating on SubmitChanges().
using (DataClasses1DataContext db = new DataClasses1DataContext())
{
tbl_Inventoryv2 inv = new tbl_Inventoryv2();
inv.Title = addTitleTextBox.Text;
inv.Model = addModelTextBox.Text;
inv.Category = addCategoryTextBox.Text;
inv.Quantity = int.Parse(addQuantityTextBox.Text);
inv.Price = decimal.Parse(addPriceTextBox.Text);
inv.Description = addDescriptionTextBox.Text;
db.tbl_Inventoryv2s.InsertOnSubmit(inv);
db.SubmitChanges();
int id = inv.IdInventory;
MessageBox.Show($"Item creation successful. Item number is {id}");
}
My database does have a primary key called IdInventory that is set to increment. Within the program, the correct increments are working as shown in my MessageBox statement above, but it never actually gets saved to the database. I have also checked the properties of the database file in Visual Studio and the path to the database is correct, as well as the Copy to Output Directory is set to Copy if Newer. Most of the questions I have looked up indicate that is usually the problem, but that doesn't look like the case for me. I am new to SQL and interacting with it via Visual Studio/c#, and SQL in general, so any input is greatly appreciated.

SqlDependency not working with Existing Database

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>”

DROP command denied to user X for table 'Y'

We are getting ready for a big SQL migration.
Currently, I have the code written, and I am testing it out with data on my local machine.
Step 1 is to throw out the existing data in the table before I import the new stuff:
using (var txn = m_mySqlConnection.BeginTransaction()) {
using (var cmd = new MySqlCommand("TRUNCATE TABLE `blah_blah`;", m_mySqlConnection, txn)) {
cmd.ExecuteNonQuery();
}
// other code
}
But, the TRUNCATE command is throwing an exception whenever I try to execute it with the MySQL user account I am running the code with:
I tried going into MySQL Workbench to give this userid DROP permission, but all I could find was a way to add DROP under the View section.
I tried that, but it did not work.
How do I go about giving this user the ability to remove the data in these tables so that I can test my populate script?
TRUNCATE deletes the table. Try using DELETE FROM Table.

Database already exist. Choose a Different Name using CreateDatabase()

I got an issue and learned something at the same time....
I created a DBML from an existing server database.
From the DBML I wanted to create local database (an .mdf file). I created the database using DataContext.CreateDatabase("C:\xxxx.mdf") .
Then I decided to delete it (MANUALLY, which is a bad thing evidentally) because when I try to recreate the database with the same name (eventhough the files are deleted), I get the error Database already exist. Choose a Different Name using CreateDatabase()
I tried looking through the registry, no luck... I tried searching the whole hard drive for the file.. no luck.
After googling, I found that you delete a database that was created with CreateDatabase() with DeleteDatabase().... Then you can recreate the database again.
Well problem is, now I still can't recreate the old database because the system thinks the name already exists.
Is there a way to get rid of the reminents of the old databse file the "does not exist"
You need to open master database via server explorer in Visual Studio (Add New Connection + Select master database) then add a New query, type Drop Database xxxx and execute it. You can also use Sql Server Management Studio.
A solution (via here) is to use SSEUtil to detach the existing db:
try
{
// open a connection to the database for test
}
catch (SystemException ex) // Change exception type based on your underlying data provider
{
if (ex.Message.ToLower().Contains("already exists. choose a different database name"))
{
var match = Regex.Match(ex.Message, "database '(.*)' already exists.",
RegexOptions.IgnoreCase);
if (match.Success)
{
String dbFileName = match.Groups[1].Value;
Process p = new Process();
p.StartInfo.UseShellExecute = true;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo.FileName = String.Format("{0}/Tools/SSEUtil.exe",
Environment.CurrentDirectory);
p.StartInfo.WorkingDirectory = Environment.CurrentDirectory;
p.StartInfo.Arguments = String.Format("-d \"{0}\"", dbFileName);
p.Start();
}
}
}
Here's a quick fix for a localDB mess. Just connect to (localdb)\MSSQLLocalDB in SQL Mgmt. Studio/Visual Studio.
Then delete the offender, checking "Close existing connections"
I also actually had this same problem. Previously, I deleted
(cut) the database in mysqlserver2012 and copied it to my application folder. After I made my app I got this error, and solved it by removing the Initial Catalog part of my Connection String.
Your final connection string should look something like this:
Data Source=<your server name>;AttachDbFileName=database path\databaseName.mdf;Integrated Security=True" + ";User Instance=True" + ";Context Connection=False;

Can not call sp_detach_db on a database that is offline

I can run this command in SqlManager to detach the db
ALTER DATABASE mydb SET OFFLINE WITH ROLLBACK IMMEDIATE
GO
dbo.sp_detach_db #dbname = N'mydb',#keepfulltextindexfile = N'false'
When I use the same connection running the same commadn via ado.net fails with error:
The database 'mydb' can not be opened because it is offline
(Error is translated from german.)
The Ado.Net code is
SqlCommand cmdOffline = new SqlCommand(#"ALTER DATABASE mydb SET OFFLINE WITH ROLLBACK IMMEDIATE");
cmdOffline.Connection = prepareMasterDBConnection;
cmdOffline.ExecuteNonQuery();
SqlCommand cmdDetach = new SqlCommand(#"dbo.sp_detach_db #dbname = N'mydb',#keepfulltextindexfile = N'false'");
cmdDetach.Connection = prepareMasterDBConnection;
cmdDetach.ExecuteNonQuery();
The connection is set to master - DB and open. The first commadn exceutes sucessfully.
What is the difference here when calling the code from ado and from sql-manager?
If your goal is to avoid conflicting connections while dropping it, rather than setting it offline before detaching, I would use the command, ALTER DATABASE mydb SET SINGLE_USER WITH ROLLBACK IMMEDIATE instead of setting it offline (and reverse it with ALTER DATABASE mydb SET MULTI_USER).
Detach needs to do some stuff before it detaches. Like s_detach says (my bold)
#skipchecks = 'skipchecks'
Specifies whether to skip or run
UPDATE STATISTIC. skipchecks is a
nvarchar(10) value, with a default
value of NULL. To skip UPDATE
STATISTICS, specify true. To
explicitly run UPDATE STATISTICS,
specify false.
By default, UPDATE STATISTICS is
performed to update information about
the data in the tables and indexes in
the SQL Server 2005 Database Engine.
Performing UPDATE STATISTICS is useful
for databases that are to be moved to
read-only media.
When it's offline, you can't do that...

Categories