Unable to restore database - sql-server

I'm trying to write a program that will restore many databases, query them using LINQ and then write recieved data to my database.
The first problem I've encountered is that I can't restore any database programatically.
The error says something like this:
"File 'xxx' cannot be restored to 'C:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\xxx.mdf'. Use WITH MOVE to identify a valid location for the file."
I've checked and that's indeed a problem. I haven't got this folder (\MSSQL11.SQLEXPRESS). How to resolve this?
My code for restoring:
private void RestoreDB(string destPath, string dbName, string fileName)
{
var myServer = new Server(#"LOCALHOST");
var res = new Restore();
res.Database = dbName;
res.Action = RestoreActionType.Database;
res.Devices.AddDevice(destPath, DeviceType.File);
res.PercentCompleteNotification = 10;
res.ReplaceDatabase = true;
try
{
res.SqlRestore(myServer);
}
catch (Exception e)
{
Console.WriteLine($"{dbName} couldn't be restored");
return;
}
}
The thing is, I've recently migrated from once PC to another. It worked before but I recall that I've had some problems with SQL before as well. I've read something about this error but I need explanation step by step how to deal with it.

Related

Setup Database before run ui coded tests on Visual Studio 2010

I'm automating UI tests to my Silverlight App and I'm using Visual Studio 2010 for it. Some tests required a setup to my Oracle Database.
Things i've done:
1 - A setup.sql file where I connect to my Database and perform actions on it. I had this file as an existing item to my project and I add as a Deployment on TestSettings.
Code:
CONNECT USERNAME#DATABASE,
CREATE TABLE TABLE_NAME,
EXIT
2 - A set.bat file where I call the setup.sql file. I had the path of this file on Setup and Cleanup tab on TestSetings.
Code:
sqlcmd -S MARIALISBOA -i setup.sql
3 - I wrote a TestInitilize method on my TestClass.
Code:
[TestInitialize()]
public void Initialize()
{
System.Diagnostics.Process.Start("setup.bat");
}
4 - I connected do my Database throw Visual Studio (Data -> Add New Data Source).
I run a test on Visual Studio but the class isn't created on my database.
Could anyone help me? I'm trying to solve this problem since Monday and I starting to lose my mind
While it does not solve your initial problem, a solution would be to use something similiar to this;
Do not create the table within your tests. this should be created on install of the Test Environment
Clear down the table for each test you want to do using a Helper Method within the test.
For example (Please note that this is SQL Server, use OLE DB connection or similiar);
internal static object FireSqlStatement(string sqlStatement)
{
object result = null;
using (var cn = new SqlConnection(ConfigurationManager.ConnectionStrings[connectionString].ConnectionString))
{
cn.Open();
var cmd = new SqlCommand
{
CommandText = sqlStatement,
CommandType = CommandType.Text,
Connection = cn
};
result = cmd.ExecuteScalar();
cmd.Dispose();
cn.Close();
}
return result;
}
An example of how I use this within my test;
[Test]
public void GetUserTriggers()
{
//Insert Test Record
Helper.FireSqlStatement("INSERT INTO [Users].[Triggers] (Id) VALUES (1)");
var request = new GetTriggersRequest()
{
TriggerType = TriggerType.UserTrigger
};
var response = ServiceInvoker.Invoke<IReports,
GetTriggersRequest, GetTriggersResponse>(
"Reports",
request,
(proxy, req) => proxy.GetTriggers(req));
foreach (var t in response.Triggers)
{
Console.WriteLine(t.Id.ToString());
}
Assert.NotNull(response);
Assert.NotNull(response.Triggers);
Assert.Greater(response.Triggers.Count, 0);
}
In your case, you could call;
Helper.FireSqlStatement("TRUNCATE TABLE tableName");
Any good?

"Cannot drop database because it is currently in use". How to fix?

Having this simple code I get "Cannot drop database "test_db" because it is currently in use" (CleanUp method) as I run it.
[TestFixture]
public class ClientRepositoryTest
{
private const string CONNECTION_STRING = "Data Source=.;Initial Catalog=test_db;Trusted_Connection=True";
private DataContext _dataCntx;
[SetUp]
public void Init()
{
Database.SetInitializer(new DropCreateDatabaseAlways<DataContext>());
_dataCntx = new DataContext(CONNECTION_STRING);
_dataCntx.Database.Initialize(true);
}
[TearDown]
public void CleanUp()
{
_dataCntx.Dispose();
Database.Delete(CONNECTION_STRING);
}
}
DataContext has one property like this
public DbSet<Client> Clients { get; set; }
How can force my code to remove database?
Thanks
The problem is that your application probably still holds some connection to the database (or another application holds connection as well). Database cannot be deleted where there is any other opened connection. The first problem can be probably solved by turning connection pooling off (add Pooling=false to your connection string) or clear the pool before you delete the database (by calling SqlConnection.ClearAllPools()).
Both problems can be solved by forcing database to delete but for that you need custom database initializer where you switch the database to single user mode and after that delete it. Here is some example how to achieve that.
I was going crazy with this! I have an open database connection inside SQL Server Management Studio (SSMS) and a table query open to see the result of some unit tests. When re-running the tests inside Visual Studio I want it to drop the database always EVEN IF the connection is open in SSMS.
Here's the definitive way to get rid of Cannot drop database because it is currently in use:
Entity Framework Database Initialization
The trick is to override InitializeDatabase method inside the custom Initializer.
Copied relevant part here for the sake of good DUPLICATION... :)
If the database already exist, you may stumble into the case of having
an error. The exception “Cannot drop database because it is currently
in use” can raise. This problem occurs when an active connection
remains connected to the database that it is in the process of being
deleted. A trick is to override the InitializeDatabase method and to
alter the database. This tell the database to close all connection and
if a transaction is open to rollback this one.
public class CustomInitializer<T> : DropCreateDatabaseAlways<YourContext>
{
public override void InitializeDatabase(YourContext context)
{
context.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction
, string.Format("ALTER DATABASE [{0}] SET SINGLE_USER WITH ROLLBACK IMMEDIATE", context.Database.Connection.Database));
base.InitializeDatabase(context);
}
protected override void Seed(YourContext context)
{
// Seed code goes here...
base.Seed(context);
}
}
This is a really aggressive database (re)initializer for EF code-first with migrations; use it at your peril but it seems to run pretty repeatably for me. It will;
Forcibly disconnect any other clients from the DB
Delete the DB.
Rebuild the DB with migrations and runs the Seed method
Take ages! (watch the timeout limit for your test framework; a default 60 second timeout might not be enough)
Here's the class;
public class DropCreateAndMigrateDatabaseInitializer<TContext, TMigrationsConfiguration>: IDatabaseInitializer<TContext>
where TContext: DbContext
where TMigrationsConfiguration : System.Data.Entity.Migrations.DbMigrationsConfiguration<TContext>, new()
{
public void InitializeDatabase(TContext context)
{
if (context.Database.Exists())
{
// set the database to SINGLE_USER so it can be dropped
context.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, "ALTER DATABASE [" + context.Database.Connection.Database + "] SET SINGLE_USER WITH ROLLBACK IMMEDIATE");
// drop the database
context.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction, "USE master DROP DATABASE [" + context.Database.Connection.Database + "]");
}
var migrator = new MigrateDatabaseToLatestVersion<TContext, TMigrationsConfiguration>();
migrator.InitializeDatabase(context);
}
}
Use it like this;
public static void ResetDb()
{
// rebuild the database
Console.WriteLine("Rebuilding the test database");
var initializer = new DropCreateAndMigrateDatabaseInitializer<MyContext, MyEfProject.Migrations.Configuration>();
Database.SetInitializer<MyContext>initializer);
using (var ctx = new MyContext())
{
ctx.Database.Initialize(force: true);
}
}
I also use Ladislav Mrnka's 'Pooling=false' trick, but I'm not sure if it's required or just a belt-and-braces measure. It'll certainly contribute to slowing down the test more.
None of those solutions worked for me. I ended up writing an extension method that works:
private static void KillConnectionsToTheDatabase(this Database database)
{
var databaseName = database.Connection.Database;
const string sqlFormat = #"
USE master;
DECLARE #databaseName VARCHAR(50);
SET #databaseName = '{0}';
declare #kill varchar(8000) = '';
select #kill=#kill+'kill '+convert(varchar(5),spid)+';'
from master..sysprocesses
where dbid=db_id(#databaseName);
exec (#kill);";
var sql = string.Format(sqlFormat, databaseName);
using (var command = database.Connection.CreateCommand())
{
command.CommandText = sql;
command.CommandType = CommandType.Text;
command.Connection.Open();
command.ExecuteNonQuery();
command.Connection.Close();
}
}
I try adding Pooling=false like Ladislav Mrnka said but always got the error.
I'm using Sql Server Management Studio and even if I close all the connection, I get the error.
If I close Sql Server Management Studio then the Database is deleted :)
Hope this can helps
I got the same error. In my case, I just closed the connection to the database and then re-connected once the in my case the new model was added and a new controller was scaffolded. That is however a very simple solution and not recommended for all scenarios if you want to keep your data.
I got the same problem back then. Turns out the solution is to close the connection in Server Explorer tab in Visual Studio. So maybe you could check whether the connection is still open in the Server Explorer.
Its simple because u're still using the same db somewhere, or a connection is still open.
So just execute "USE master" first (if exist, but usually is) and then drop the other db. This always should work!
Grz John

How to delete server entries in SQL Server Management Studio's "Connect to Server" Screen? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to remove “Server name” items from history of SQL Server Management Studio
In the "Connect to Server" screen, SQL Server Management Studio stores all entries you have ever entered for Server Name, login and password. This is very helpful, but from time to time things change, servers addresses change, databases are no longer available.
How can I delete server entries from this screen? Also, when you select a server, past logins are available in the list. Once again, these change. How can I delete user entries?
Looks like this file is a binary serialized version of the Microsoft.SqlServer.Management.UserSettings.SqlStudio class defined in the Microsoft.SqlServer.Management.UserSettings, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91 assembly (located at c:\Program Files\Microsoft SQL Server\100\Tools\Binn\VSShell\Common7\IDE\Microsoft.SqlServer.Management.UserSettings.dll).
With a bit of development skill (Visual Studio or even Powershell) you can deserialize this file into the original class, find the entries you want to remove and re-serialize the file back out.
This should give you the idea (working on a copy of the .bin file)...
var binaryFormatter = new BinaryFormatter();
var inStream = new MemoryStream(File.ReadAllBytes(#"c:\temp\SqlStudio.bin"));
var settings = (SqlStudio) binaryFormatter.Deserialize(inStream);
foreach (var pair in settings.SSMS.ConnectionOptions.ServerTypes)
{
ServerTypeItem serverTypeItem = pair.Value;
List<ServerConnectionItem> toRemove = new List<ServerConnectionItem>();
foreach (ServerConnectionItem server in serverTypeItem.Servers)
{
if (server.Instance != "the server you want to remove")
{
continue;
}
toRemove.Add(server);
}
foreach (ServerConnectionItem serverConnectionItem in toRemove)
{
serverTypeItem.Servers.RemoveItem(serverConnectionItem);
}
}
MemoryStream outStream = new MemoryStream();
binaryFormatter.Serialize(outStream, settings);
byte[] outBytes = new byte[outStream.Length];
outStream.Position = 0;
outStream.Read(outBytes, 0, outBytes.Length);
File.WriteAllBytes(#"c:\temp\SqlStudio.bin", outBytes);
After Adrian's question, I tried this again on a Win7 x64 box using Visual Studio 2010. I found the same error so, after digging a bit I found it took a number of steps to resolve.
Set the Platform target to 'x86' in the project properties
add a reference to Microsoft.SqlServer.Management.SDK.SqlStudio (on my box this was at c:\Program Files\Microsoft SQL Server\100\Tools\Binn\VSShell\Common7\IDE\Microsoft.SqlServer.Management.Sdk.SqlStudio.dll)
add a reference to Microsoft.SqlServer.Management.UserSettings (in the same directory at the previous one)
perform custom assembly resolution
The custom assembly resolution took a bit of doing since it wasn't obvious (to me, at least) why the CLR wouldn't just resolve the assembly correctly and why Visual Studio wouldn't allow me to add the reference manually. I'm talking about the SqlWorkbench.Interfaces.dll.
The updated code looks like this:
internal class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
var binaryFormatter = new BinaryFormatter();
var inStream = new MemoryStream(File.ReadAllBytes(#"c:\temp\SqlStudio.bin"));
var settings = (SqlStudio) binaryFormatter.Deserialize(inStream);
foreach (var pair in settings.SSMS.ConnectionOptions.ServerTypes)
{
ServerTypeItem serverTypeItem = pair.Value;
List<ServerConnectionItem> toRemove = new List<ServerConnectionItem>();
foreach (ServerConnectionItem server in serverTypeItem.Servers)
{
if (server.Instance != "the server you want to remove")
{
continue;
}
toRemove.Add(server);
}
foreach (ServerConnectionItem serverConnectionItem in toRemove)
{
serverTypeItem.Servers.RemoveItem(serverConnectionItem);
}
}
MemoryStream outStream = new MemoryStream();
binaryFormatter.Serialize(outStream, settings);
byte[] outBytes = new byte[outStream.Length];
outStream.Position = 0;
outStream.Read(outBytes, 0, outBytes.Length);
File.WriteAllBytes(#"c:\temp\SqlStudio.bin", outBytes);
}
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
Debug.WriteLine(args.Name);
if (args.Name.StartsWith("SqlWorkbench.Interfaces"))
{
return Assembly.LoadFrom(#"C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\VSShell\Common7\IDE\SqlWorkbench.Interfaces.dll");
}
return Assembly.Load(args.Name);
}
}
Unfortunately, it does not appear to be possible (or at least practical) to only remove certain items.
However, if you want, you can reset the configuration and start from scratch.
Make sure Management Studio is closed, then delete or rename this file:
%APPDATA%\Microsoft\Microsoft SQL Server\100\Tools\Shell\SqlStudio.bin
Note that that file contains other user preference settings, so if you've customized your Management Studio configuration, you'll have some work to do restoring them.
Reference: http://social.msdn.microsoft.com/Forums/en-US/sqltools/thread/94e5c3ca-c76d-48d0-ad96-8348883e8db8/
Good luck!

cannot read SQLite database file in an Eclipse Plugin project

I am REALLY new to Eclipse plugin developement, so maybe my question sounds dumb, but I've been googling for hours...
Whats the way to load an SQLite db into my Eclipse plugin?
First I created a standalone Java application, it loaded, and processed the database file just file, but when I added the code (well copied the files to the new project) it says:
java.sql.SQLException: no such table: measurement
The db file is in the projects root dir.
I thought this issue is caused becouse the applicaiton cannot find the database file, so I changed the filename from test.db to asdftest.db, and I got the same error, so the problem was this indeed.
Thanks!
Here is the code:
public List<Coord> generateModel() {
try {
Class.forName("org.sqlite.JDBC");
Connection conn = DriverManager
.getConnection("jdbc:sqlite:test.db");
Statement stat = conn.createStatement();
ResultSet rs = stat
.executeQuery("select * from measurement where has_gps = 'TRUE';");
LinkedList<Coord> nodes = new LinkedList<Coord>();
while (rs.next()) {
nodes.add(new Coord(rs.getString("_id"), rs.getString("lat"),
rs.getString("lon")));
}
rs.close();
conn.close();
return nodes;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

How to use my own sqlite database?

I put my database field in "assets" folder. And use the code from this blog to copy the database to "/data/data/my_packname/databases/", (This copy code i run it in the onCreate() method when i run this app) then use select * from ... to get data. But it gives me the exception: no such table.
Someone told me that if i am attempting to copy the file in SQLiteOpenHelper's onCreate(), it's too late. So the copy file code can not copy the complete file.
So i need to use adb or ddms to pull the database first?
So, Anyone can teach me how to use my own databse?
Can you tell me the setup?
I've used the instructions in that blog post and found them, while on the right track, to severely complicate the issue by unnecessarily extending SQLiteOpenHelper. I've had much better luck doing the following:
Create a utility class that creates the static db by copying it into the correct directory from assets, but doesn't get itself so hung up on following the SQLiteOpenHelper format.
Using the same utility class to open the db by using SQLiteDatabase.openDatabase()
Edit: Here is a version of this utility class I've created; it's not quite complete, but you'll get the drift.
public class DbUtils {
private static final String DB_PATH = "/data/data/com.mypackage.myapp/databases/";
private static final String DB_NAME = "my.db";
public static void createDatabaseIfNotExists(Context context) throws IOException {
boolean createDb = false;
File dbDir = new File(DB_PATH);
File dbFile = new File(DB_PATH + DB_NAME);
if (!dbDir.exists()) {
dbDir.mkdir();
createDb = true;
}
else if (!dbFile.exists()) {
createDb = true;
}
else {
// Check that we have the latest version of the db
boolean doUpgrade = false;
// Insert your own logic here on whether to upgrade the db; I personally
// just store the db version # in a text file, but you can do whatever
// you want. I've tried MD5 hashing the db before, but that takes a while.
// If we are doing an upgrade, basically we just delete the db then
// flip the switch to create a new one
if (doUpgrade) {
dbFile.delete();
createDb = true;
}
}
if (createDb) {
// Open your local db as the input stream
InputStream myInput = context.getAssets().open(DB_NAME);
// Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(dbFile);
// transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
// Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
}
}
public static SQLiteDatabase getStaticDb() {
return SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);
}
}
After you've copied the database, you should try closing and reopening the SQLiteDatabase object before executing any query on it. I had a similar problem with copying a db from an input stream and that's what solved it for me.
here is my Version from "Silvio Donnini" Code :),
now you can update the Database easily.
private static final String DB_PATH = "/data/data/pakagename/databases/";
private static final String DB_NAME = "databaseName";
private static SQLiteDatabase db;
public static void createDatabaseIfNotExists(Context context,int version) throws IOException {
boolean createDb = false;
File dbDir = new File(DB_PATH);
File dbFile = new File(DB_PATH + DB_NAME);
if (!dbDir.exists()) {
dbDir.mkdir();
createDb = true;
}
else if (!dbFile.exists()) {
createDb = true;
}
else {
// Check that we have the latest version of the db
db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);
if (db.getVersion() != version) {
dbFile.delete();
createDb = true;
}
}
if (createDb) {
// Open your local db as the input stream
InputStream myInput = context.getResources().openRawResource(R.raw.database);
// Open the empty db as the output stream
OutputStream myOutput = new FileOutputStream(dbFile);
// transfer bytes from the inputfile to the outputfile
byte[] buffer = new byte[1024];
int length;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
// Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
SQLiteDatabase dbwrite = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READWRITE);
dbwrite.setVersion(version);
dbwrite.close();
if (db != null)
db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);
}
}
public static SQLiteDatabase getStaticDb() {
if (db != null)
return db;
return SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);
}
I know this is an old question, but I lost a lot of time figuring it out, with the help of all the replies.
The issue is that a device stores a database in his data/data/.../databases folder. So, when you change sth about the database (name, add android metadata table, size..) it wont make any difference because of the stored database and the method that checked for existing database.
To get the newest database, after changing it, you must run the program without checking for existing databses (e.g. instead of dbExist = checkDataBase(); make it just false).
dbExist = checkDataBase();
Change to:
dbExists = false;
After you picked up the "new" databse you can return to checking the existing ones.
Hope it helps someone,
dina
I know this is an old post, but for those who still get here after a Google or a Bing search, this is the solution to the stated problem:
in createDataBase() there is the following check;
this.getReadableDatabase();
This checks if there is already a database with the provided name and if not creates an empty database such that it can be overwritten with the one in the assets folder. On newer devices this works flawlessly but there are some devices on which this doesn't work. Mainly older devices. I do not know exactly why, but it seems like the getReadableDatabase() function not only gets the database but also opens it. If you then copy the database from the assets folder over it, it still has the pointer to an empty database and you will get table does not exist errors.
So in order to make it work on all devices you should modify it to the following lines:
SQLiteDatabase db = this.getReadableDatabase();
if (db.isOpen()){
db.close();
}
Even if the database is opened in the check, it is closed thereafter and it will not give you any more trouble.
Calm down guys,After long research finally found silly mistake for "no such table" error
Check name of database in Assets folder if it's like "DATABASE_NAME.EXTENSION" then put full name in Helper class with extension its solved my problem.
like say in Assets name of database is login.sqlite or login.db anything. put DB_NAME=login.sqlite fully with extention.
this tutorial now works perfectly.
The way of creating database from article you've posted is slightly diffrent from that how it's done in android examples (I don't want to say if it's good or bad).
I've learned how to use databases from SDKs NotePad sample
It's good example to start from, becouse it covers both database creation topic and database access through ContentProvider (it's really the only good way to get data from db, otherwise you will have problems when trying to get data simultaneusly from many places of your code).
You should note that SQLiteOpenHelper is really powerful and "it will help you" if you will use it properly. For example it stores current database version (not sqlite version but number you assingn with database schema version) and when you create new application version with new database structure you can update current schema to the new version in onUpdate.

Resources