How do I make sure alla data is restored using SMO? - sql-server

A restore performed with C# code using SMO objects restores fine when original database is in SIMPLE recovery mode. We got problems with one database where the restore missed all content from a certain table, where all data was inserted late in process. The database showed to be in BULK LOGGED recovery mode. After changing to SIMPLE and doing a new backup, it restored fine, using our code.
We have tried different settings on the restore object, but found none that fixes the problem. We are under the impression that the restoring ignores data in the log.
The basic restore looks like this:
sqlServer = new Server(new ServerConnection(instanceName));
restore = GetRestore();
restore.PercentComplete += PercentCompleteAction;
restore.Complete += CompleteAction;
restore.SqlRestore(sqlServer);
the GetRestore function is basically implemented like this:
restore = new Restore();
var deviceItem = new BackupDeviceItem(backupFileName, DeviceType.File);
restore.Devices.Add(deviceItem);
restore.Database = newDatabaseName;
restore.NoRecovery = false;
restore.Action = RestoreActionType.Database;
restore.ReplaceDatabase = false;
return restore;
There are no error messages - just missing content in one table.
Added try:
I took a guess at the solution below, but it didn't help:
restore.ReplaceDatabase = false;
restore.NoRecovery = true;
restore.Action = RestoreActionType.Database;
restore.SqlRestore(sqlServer);
restore.ReplaceDatabase = true;
restore.NoRecovery = true;
restore.Action = RestoreActionType.Log;
restore.SqlRestore(sqlServer);
restore.ReplaceDatabase = true;
restore.NoRecovery = false;
restore.Action = RestoreActionType.Files;
restore.SqlRestore(sqlServer);

You need select a correct FileNumber in your Log file, see this method can solve your problem:
public static void restaurarBackup(string pathFileBak)
{
SqlConnection conn = new SqlConnection(Connection.getCon());
Server smoServer = new Server(new ServerConnection(conn));
string localFilePath = pathFileBak;
string db_name = "ETrade";
string defaultFolderEtrade = #"C:\ETrade\";
Restore rs = new Restore();
rs.NoRecovery = false;
rs.ReplaceDatabase = true;
BackupDeviceItem bdi = default(BackupDeviceItem);
bdi = new BackupDeviceItem(localFilePath, DeviceType.File);
rs.Devices.Add(bdi);
DataTable dt = rs.ReadFileList(smoServer);
foreach (DataRow r in dt.Rows)
{
string logicalFilename = r.ItemArray[dt.Columns["LogicalName"].Ordinal].ToString();
string physicalFilename = defaultFolderEtrade + Path.GetFileName(r.ItemArray[dt.Columns["PhysicalName"].Ordinal].ToString());
rs.RelocateFiles.Add(new RelocateFile(logicalFilename, physicalFilename));
}
DataTable backupHeaders = rs.ReadBackupHeader(smoServer);
rs.FileNumber = Convert.ToInt32(backupHeaders.AsEnumerable().Max(backupInfo => backupInfo["Position"]));
rs.Database = db_name;
smoServer.KillAllProcesses(rs.Database);
Microsoft.SqlServer.Management.Smo.Database db = smoServer.Databases[rs.Database];
db.DatabaseOptions.UserAccess = DatabaseUserAccess.Single;
rs.SqlRestore(smoServer);
db = smoServer.Databases[rs.Database];
db.SetOnline();
smoServer.Refresh();
db.Refresh();
}
If you want look backups in your Log file, see this query:
SELECT database_name, name, backup_start_date,
backup_finish_date, datediff(mi, backup_start_date, backup_finish_date) [tempo (min)],
position, first_lsn, last_lsn, server_name, recovery_model,
type, cast(backup_size/1024/1024 as numeric(15,2)) [Tamanho (MB)], B.is_copy_only
FROM msdb.dbo.backupset B

Related

Update Local and Web database from codeigniter website

I have a Codeigniter website that is hosted on a global server and connected to the global database.
I want to connect another database that is hosted locally(192.168.x.x).
Is there any way to achieve this?
In real-world CodeIgniter projects, developers need to work with multiple databases at the same time. This presents a unique challenge to developers. Since this is a common enough problem, CodeIgniter offers a simple solution for it.
In order to use multiple database connections in your CodeIgniter project, you just need to create multiple configuration arrays that simplify working with multiple databases.
The Default Configuration Array
Following is the structure of the default Codeigniter database configuration array:
$db['default']['hostname'] = 'localhost';
$db['default']['username'] = 'root';
$db['default']['password'] = '';
$db['default']['database'] = 'mydefaultdatabase';
$db['default']['dbdriver'] = 'mysql';
$db['default']['dbprefix'] = '';
$db['default']['pconnect'] = TRUE;
$db['default']['db_debug'] = FALSE;
$db['default']['cache_on'] = FALSE;
$db['default']['autoinit'] = FALSE;
$db['default']['stricton'] = FALSE;
$db['default']['cachedir'] = '';
$db['default']['char_set'] = 'utf8';
$db['default']['dbcollat'] = 'utf8_general_ci';
$db['default']['swap_pre'] = '';
So in order to create another database connection, you should create another configuration array. This array has to follow the same structure. Here is an example of the array:
$db['anotherdb']['hostname'] = 'XXX.XXX.X.XXX';
$db['anotherdb']['username'] = 'another_user';
$db['anotherdb']['password'] = '';
$db['anotherdb']['database'] = 'anotherdatabase';
$db['anotherdb']['dbdriver'] = 'mysql';
$db['anotherdb']['dbprefix'] = '';
$db['anotherdb']['pconnect'] = TRUE;
$db['anotherdb']['db_debug'] = FALSE;
$db['anotherdb']['cache_on'] = FALSE;
$db['anotherdb']['cachedir'] = '';
$db['anotherdb']['char_set'] = 'utf8';
$db['anotherdb']['dbcollat'] = 'utf8_general_ci';
$db['anotherdb']['swap_pre'] = '';
$db['anotherdb']['autoinit'] = FALSE;
$db['anotherdb']['stricton'] = FALSE;
Connect to the Right Database
At this point, you have two databases in your sample project. To connect to a specific database, you must specify the database name. Here is the proper syntax:
this->load->database(anotherdb, TRUE)
After connecting to the database, you can perform databse operations as shown below:
load 'anotherdatabase'
$this->legacy_db = $this->load->database(anotherdatabase, true);
Fetch result from 'mydefaultdatabase'
$this->legacy_db->select ('*');
$this->legacy_db->from ('mydefaultdatabase');
$query = $this->legacy_db->get();
$result = $query->result ();
Now if you need to work with the second database, you have to send the connection to a variable that is usable in your model function:
function db_calling_model_method()
{
$otherdb = $this->load->database('anotherdb', TRUE); // the TRUE paramater tells CI that you'd like to return the database object.
$query = $otherdb->select('column_one, column_two')->get('table');
var_dump($query);
}
Close the Connections
CodeIgniter does close the database connections after it determines that the code no longer need the connection. However, as a good practice, developers should close the connections explicitly. Here is how to take care of the issue:
$this->db->close(); // for default Connection
$this->legacy_db->close(); //

SQL Server DAC FX SchemaComparison SchemaCompareDatabaseEndpoint fails with no IntegratedSecuirty

I am trying to find newly created tables in the target database on publishing. Using DAC Fx I am able to find the differences and delete the tables after moving the newly created table to another db.
I developed and tested the code with IntegratedSecurity. Started failing on machines with SQLServer logins.
The moment I toggle the IntegratedSecurity to true it works. Is it a bug?
private void Analyse()
{
try
{
var sourceDacpac = new SchemaCompareDacpacEndpoint(DacPacSrc);
var csb = new SqlConnectionStringBuilder(ConnectionString);
csb.IntegratedSecurity = false;
var targetDatabase =new SchemaCompareDatabaseEndpoint(csb.ToString());
var comparison = new SchemaComparison(sourceDacpac, targetDatabase);
comparison.Options.DropObjectsNotInSource = true;
var result = comparison.Compare();
if (result.GetErrors().Any())
{
throw new Exception("Compare failed " + result.GetErrors().FirstOrDefault().Message);
}
var delta = new List<string>();
if (result.Differences != null && result.Differences.Any())
{
var deltaTables = result.Differences.Where(x => x.Name == "Table" && x.UpdateAction == SchemaUpdateAction.Delete);
delta = deltaTables.Select(x => x.TargetObject.Name.ToString()).ToList();
}
FindingDeltaCompleted?.Invoke(this, new DeltaEventArgs(delta));
}
catch (Exception ex)
{
Logging.HandleException(ex);
}
}
Try setting Persist Security Info=True in the SQL Authentication connection string.
SSDT/DAC Fx saves connection strings in registry under HKEY_CURRENT_USER\SOFTWARE\Microsoft\SSDT\ConnectionStrings. When Persist Security Info=True is not set, it won't restore the password when loading the connection strings from registry.

Nunit database rollback

I'm fairly new to using Nunit as a test framework and have come across something I don't really understand.
I am writing an integration test which inserts a row into a database table. As I want to repeatedly run this test I wanted to delete the row out once the test has completed. The test runs fine, however when I look in the database table the row in question is still there even though the delete command ran. I can even see it run when profiling the database whilst running the test.
Does Nunit somehow rollback database transaction? If anyone has any ideas why I am seeing this happen please let me know. I have been unable to find any information about Nunit rolling back transactions which makes me think I'm doing something wrong, but the test runs the row appears in the database it is just not being deleted afterwards even though profiler shows the command being run!
Here is the test code I am running
[Test]
[Category("Consultant split integration test")]
public void Should_Save_Splits()
{
var splitList = new List<Split>();
splitList.Add(new Split()
{
UnitGroupId = 69,
ConsultantUserId = 1,
CreatedByUserId = 1,
CreatedOn = DateTime.Now,
UpdatedByUserId = 1,
UpdatedOn = DateTime.Now,
Name = "Consultant1",
Unit = "Unit1",
Percentage = 100,
PlacementId = 47
});
var connection = Helpers.GetCpeDevDatabaseConnection();
var repository = new Placements.ConsultantSplit.DAL.PronetRepository();
var notebookManager = Helpers.GetNotebookManager(connection);
var userManager = Helpers.GetUserManager(connection);
var placementManager = Helpers.GetPlacementManager(connection);
var sut = new Placements.ConsultantSplit.ConsultantSplitManager(repository, connection, notebookManager, userManager, placementManager);
IEnumerable<string> errors;
sut.SaveSplits(splitList, out errors);
try
{
using (connection.Connection)
{
using (
var cmd = new SqlCommand("Delete from ConsultantSplit where placementid=47",
connection.Connection))
{
connection.Open();
cmd.CommandType = CommandType.Text;
connection.UseTransaction = false;
cmd.Transaction = connection.Transaction;
cmd.ExecuteNonQuery();
connection.Close();
}
}
}
catch (Exception exp)
{
throw new Exception(exp.Message);
}

Data insertion in Sql Table is taking too much time

I am inserting data in the sql server.Here is the code:
SqlParameter[] param = new SqlParameter[1];
param[0] = new SqlParameter();
param[0].ParameterName = "#Exch";
param[0].SqlDbType = SqlDbType.Int;
param[0].Value = "BSE";
formObjSqlConnection.SQLConnection.Executes("LPExch..DeleteVarMargin", param);
foreach (BseVar objBseVar in objListNseData)
{
currentIndex++;
param = new SqlParameter[10];
param[0] = new SqlParameter();
param[0].ParameterName = "#Exch";
param[0].SqlDbType = SqlDbType.Char;
param[0].Value = "BSE";
param[1] = new SqlParameter();
param[1].ParameterName = "#Symbol";
param[1].SqlDbType = SqlDbType.Char;
param[1].Size = 10;
param[1].Value = objBseVar.Symbol;
param[2] = new SqlParameter();
param[2].ParameterName = "#Series";
param[2].SqlDbType = SqlDbType.Char;
param[2].Value = "EQ";
param[3] = new SqlParameter();
param[3].ParameterName = "#SecurityVar";
param[3].SqlDbType = SqlDbType.SmallMoney;
param[3].Value = objBseVar.SecurityVar;
param[4] = new SqlParameter();
param[4].ParameterName = "#IndexVar";
param[4].SqlDbType = SqlDbType.SmallMoney;
param[4].Value = 0;
param[5] = new SqlParameter();
param[5].ParameterName = "#VarMargin";
param[5].SqlDbType = SqlDbType.SmallMoney;
param[5].Value = objBseVar.IndexVar;
param[6] = new SqlParameter();
param[6].ParameterName = "#AdhocMargin";
param[6].SqlDbType = SqlDbType.SmallMoney;
param[6].Value = objBseVar.SecurityVar - objBseVar.IndexVar;
param[7] = new SqlParameter();
param[7].ParameterName = "#VarMarginRate";
param[7].SqlDbType = SqlDbType.SmallMoney;
param[7].Value = objBseVar.IndexVar;
formObjSqlConnection.SQLConnection.Executes("LPExch..UpdateOrAddCashVarMarginBSE", param);
if (Convert.ToInt32(1 / progressChange * currentIndex) <= 100)
objImportMaster.UpdateProgressBar(Convert.ToInt32(1 / progressChange * currentIndex));
}
formObjSqlConnection.SQLConnection.Executes("LPExch..UpdateCashVarMarginBSEScripNo");
Is there any other way i can insert the data in the database.The problem is that database is taking too much time to insert the data.Also i am updating the progressbar in other UI.
Is that the reason for slow insertion?
Can we use any other way to insert data.?
Right now you are sending every insert one at a time. That's slow. If you can change the database, look up table valued parameters and pass a table to your function so you can send all the records just once.
If you have direct access to a table, you can also use bulk copy.
If you are trying to insert many records then consider using bulk copy, it is quite fast.
An example is available here.

How to programmatically export SQL schema using Microsoft.SqlServer.Management.Smo

I've built a simple utility in C# that uses Microsoft.SqlServer.Management.Smo objects to export a database schema. This has been working great until I added a full text index.
When it exports the SQL for creating a full text index it does not include the columns that are defined in the index. For example, suppose I have a table named "Recipes" with 2 columns included in the FT index named "RecipeName" "Description". Dumping the schema using my utility produces the following SQL:
CREATE FULLTEXT INDEX ON [dbo].[Recipes]
KEY INDEX [PK_Recipes]ON ([ft], FILEGROUP [PRIMARY])
WITH (CHANGE_TRACKING = AUTO, STOPLIST = SYSTEM)
What I expect to be dumped is this (notice the columns):
CREATE FULLTEXT INDEX ON [dbo].[Recipes](
[Description] LANGUAGE [English],
[RecipeName] LANGUAGE [English]
)
KEY INDEX [PK_Recipes]ON ([ft], FILEGROUP [PRIMARY])
WITH (CHANGE_TRACKING = AUTO, STOPLIST = SYSTEM)
Here's the C# that generates the schema from a database file:
static void GenerateScript(string sourceDbPath, string destinationScriptPath)
{
try
{
string connString = string.Format(#"Data Source=.;AttachDbFilename={0};Integrated Security=True;User Instance=True", sourceDbPath);
SqlConnection sqlConn = new SqlConnection(connString);
ServerConnection serverConn = new ServerConnection(sqlConn);
Server server = new Server(serverConn);
Database database = server.Databases[sourceDbPath];
Transfer transfer = new Transfer(database);
ScriptingOptions options = new ScriptingOptions();
options.AppendToFile = false; // Overwrite file
options.ClusteredIndexes = true;
options.Indexes = true;
options.DriAll = true;
options.Triggers = true;
options.Bindings = true;
options.Default = true;
options.IncludeDatabaseContext = false;
options.IncludeHeaders = true;
options.FullTextIndexes = true;
options.SchemaQualify = true;
options.SchemaQualifyForeignKeysReferences = true;
options.ScriptSchema = true;
options.ScriptData = false;
options.ScriptDrops = false;
options.FileName = destinationScriptPath;
transfer.Options = options;
transfer.CopyAllFullTextCatalogs = true;
transfer.CopyAllFullTextStopLists = true;
transfer.CopyAllTables = true;
transfer.ScriptTransfer();
}
catch(Exception ex)
{
Console.WriteLine(ex.ToString());
Environment.Exit(-1);
}
}
Can anyone spot what I'm missing?
I was unable to find a combination of scripting options that would include the columns in the full text index create statement.
So instead I queried the database for the full text index information by executing the sp_help_fulltext_tables and sp_help_fulltext_columns stored procs. This allowed me to construct the statements by hand.
Not ideal but it works.

Resources