Deploying a project that includes an MDF file to an external computer - deployment

Basically, I have a Windows Forms Application that includes a dataGridView with the DataSource being an MDF file named VoRteXData.mdf. Now, I need to deploy this to an external location. For my forms code, it includes:
private void Form1_Load(object sender, EventArgs e)
{
SqlConnection sqlCon = new SqlConnection();
sqlCon.ConnectionString = #"Data Source=.\SQLEXPRESS;AttachDbFilename=C:\Users\Moderator\Documents\VoRteXData.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True";
sqlCon.Open();
SqlDataAdapter sda = new SqlDataAdapter("select * from VoRteXBanTable", sqlCon);
DataTable dt = new DataTable();
sda.Fill(dt);
dataGridView1.DataSource = dt;
}
private void button1_Click(object sender, EventArgs e)
{
string searchFilter = textBox1.Text;
for (int i = 0; i < dataGridView1.Rows.Count; i++)
{
if (dataGridView1.Rows[i].Cells[0].Value.ToString() == searchFilter)
{
dataGridView1.Rows[i].Selected = true;
dataGridView1.Rows[i].Visible = true;
}
else
{
dataGridView1.CurrentCell = null;
dataGridView1.Rows[i].Visible = false;
dataGridView1.Rows[i].Selected = false;
}
}
}
}
Next, in my MDF file is one table and 5 fields with around 50 records. Upon publishing the project to an external computer, I get an error: "A network-related or instance-specific error occurred while establishing a connection to SQL server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL server is configured to allow remote connections". However, I'm not using SQL Server Management Studio because I need to deploy this at an external location without a host. I don't want the user to install all the SQL prerequisites because, that would be ridiculous. So is there any way to get C# to run this MDF file at all? Or mabye upload it to the web for free?

The client machine must have SQL Server Express installed. You can include this in the setup.exe by including it as a prerequisite. This will only install the database engine. But, if you do not want the client machine to have SQL Server Express installed then you need to change your app to use SQL Server Compact. That way it will not need a SQL Server instance installed on the client.

Related

SQL Server 2016 list instances

I am using the code below in my windows application to get local servers, when I was using SQL Server 2012 it was working without any errors, but when I downloaded SQL Server 2016, I got the exception :
Exception: An exception occurred in SMO while trying to manage a service.
Inner Exception: Failed to retrieve data for this request.
The Code:
public List<string> findLocalServers()
{
var servers = new List<string>();
try
{
var serverCollection = new ManagedComputer().ServerInstances.Cast<ServerInstance>().Select(instance => String.IsNullOrEmpty(instance.Name) ?
instance.Parent.Name : instance.Parent.Name)
.ToArray();
foreach (var server in serverCollection.Where(server => !servers.Contains(server)))
{
servers.Add(server);
}
return servers;
}
catch (Exception ex)
{
return null;
}
}
I had same problem. These steps helped me.
Reference to Microsoft.SqlServer.ConnectionInfo increased to version 13.x.x.x (via Add reference -> and find upper version in Extensions).
Same step for Microsoft.SqlServer.Management.Sdk.Sfc and Microsoft.SqlServer.Smo.
I did not find increased version for Microsoft.SqlServer.SqlWmiManagement. So I removed reference to this assembly and via browse I founded C:\Program Files\Microsoft SQL Server\130\SDK\Assemblies\Microsoft.SqlServer.SqlWmiManagement.dll.
That´s all.

MongoDB Driver 2.0 C# is there a way to find out if the server is down? In the new driver how do we run the Ping command?

How do you call the Ping command with the new C# driver 2.0?
In the old driver it was available via Server.Ping()? Also, Is there a way to find out if the server is running/responding without running the actual query?
Using mongoClient.Cluster.Description.State doesn't help because it still gave the disconnected state even after the mongo server started responding.
You can check the cluster's status using its Description property:
var state = _client.Cluster.Description.State
If you want a specific server out of that cluster you can use the Servers property:
var state = _client.Cluster.Description.Servers.Single().State;
This worked for me on both c# driver 2 and 1
int count = 0;
var client = new MongoClient(connection);
// This while loop is to allow us to detect if we are connected to the MongoDB server
// if we are then we miss the execption but after 5 seconds and the connection has not
// been made we throw the execption.
while (client.Cluster.Description.State.ToString() == "Disconnected") {
Thread.Sleep(100);
if (count++ >= 50) {
throw new Exception("Unable to connect to the database. Please make sure that "
+ client.Settings.Server.Host + " is online");
}
}
As #i3arnon's answer I can tell it was reliable for me in this way:
var server = client.Cluster.Description.Servers.FirstOrDefault();
var serverState = ServerState.Disconnected;
if (server != null) serverState = server.State;
or in new versions of .Net
var serverState = client.Cluster.Description.Servers.FirstOrDefault()?.State
?? ServerState.Disconnected;
But if you realy want to run a ping command you can do it like this:
var command = new CommandDocument("ping", 1);
try
{
db.RunCommand<BsonDocument>(command);
}
catch (Exception ex)
{
// ping failed
}

Get connection used by DatabaseFactory.GetDatabase().ExecuteReader()

We have two different query strategies that we'd ideally like to operate in conjunction on our site without opening redundant connections. One strategy uses the enterprise library to pull Database objects and Execute_____(DbCommand)s on the Database, without directly selecting any sort of connection. Effectively like this:
Database db = DatabaseFactory.CreateDatabase();
DbCommand q = db.GetStoredProcCommand("SomeProc");
using (IDataReader r = db.ExecuteReader(q))
{
List<RecordType> rv = new List<RecordType>();
while (r.Read())
{
rv.Add(RecordType.CreateFromReader(r));
}
return rv;
}
The other, newer strategy, uses a library that asks for an IDbConnection, which it Close()es immediately after execution. So, we do something like this:
DbConnection c = DatabaseFactory.CreateDatabase().CreateConnection();
using (QueryBuilder qb = new QueryBuilder(c))
{
return qb.Find<RecordType>(ConditionCollection);
}
But, the connection returned by CreateConnection() isn't the same one used by the Database.ExecuteReader(), which is apparently left open between queries. So, when we call a data access method using the new strategy after one using the old strategy inside a TransactionScope, it causes unnecessary promotion -- promotion that I'm not sure we have the ability to configure for (we don't have administrative access to the SQL Server).
Before we go down the path of modifying the query-builder-library to work with the Enterprise Library's Database objects ... Is there a way to retrieve, if existent, the open connection last used by one of the Database.Execute_______() methods?
Yes, you can get the connection associated with a transaction. Enterprise Library internally manages a collection of transactions and the associated database connections so if you are in a transaction you can retrieve the connection associated with a database using the static TransactionScopeConnections.GetConnection method:
using (var scope = new TransactionScope())
{
IEnumerable<RecordType> records = GetRecordTypes();
Database db = DatabaseFactory.CreateDatabase();
DbConnection connection = TransactionScopeConnections.GetConnection(db).Connection;
}
public static IEnumerable<RecordType> GetRecordTypes()
{
Database db = DatabaseFactory.CreateDatabase();
DbCommand q = db.GetStoredProcCommand("GetLogEntries");
using (IDataReader r = db.ExecuteReader(q))
{
List<RecordType> rv = new List<RecordType>();
while (r.Read())
{
rv.Add(RecordType.CreateFromReader(r));
}
return rv;
}
}

How do I find the current version of a SQL Server data-tier application?

We are using a SQL Server Data-tier application (dacpac or DAC pack) and I'm having a hard time finding the current version of the database.
Is there a way to obtain the current version using any of these methods:
From within SQL Server Management Studio
Via a SQL statement
Programmatically using .NET code
From within SQL Server Management Studio
From http://msdn.microsoft.com/en-us/library/ee210574.aspx
To view the details of a DAC deployed to an instance of the Database Engine:
Select the View/Object Explorer menu.
Connect to the instance of the from the Object Explorer pane.
Select the View/Object Explorer Details menu.
Select the server node in Object Explorer that maps to the instance, and then navigate to the Management\Data-tier Applications node.
The list view in the top pane of the details page lists each DAC deployed to the instance of the Database Engine. Select a DAC to display the information in the detail pane at the bottom of the page.
The right-click menu of the Data-tier Applications node is also used to deploy a new DAC or delete an existing DAC.
Via a SQL statement
SELECT instance_name, type_version FROM msdb.dbo.sysdac_instances
Via a SQL statement on Azure
SELECT instance_name, type_version FROM master.dbo.sysdac_instances
Programmatically using .NET code
Note that in DacFx 3.0 this is no longer valid. See my other answer for a way to do it.
C#
ServerConnection serverConnection;
string databaseName;
// Establish a connection to the SQL Server instance.
using (SqlConnection sqlConnection =
new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
{
serverConnection = new ServerConnection(sqlConnection);
serverConnection.Connect();
// Assumes default database in connection string is the database we are trying to query.
databaseName = sqlConnection.Database;
}
// Get the DAC info.
DacStore dacstore = new DacStore(serverConnection);
var dacInstance = dacstore.DacInstances[databaseName];
System.Diagnostics.Debug.Print("Database {0} has Dac pack version {1}.", databaseName, dacInstance.Type.Version);
VB.NET
Dim serverConnection As ServerConnection
Dim databaseName As String
' Establish a connection to the SQL Server instance.
Using sqlConnection As New SqlConnection(ConfigurationManager.ConnectionStrings("DefaultConnection").ConnectionString)
serverConnection = New ServerConnection(sqlConnection)
serverConnection.Connect()
' Assumes default database in connection string is the database we are trying to query.
databaseName = sqlConnection.Database
End Using
' Get the DAC info.
Dim dacstore As New DacStore(serverConnection)
Dim dacInstance = dacstore.DacInstances(databaseName)
System.Diagnostics.Debug.Print("Database {0} has Dac pack version {1}.", databaseName, dacInstance.Type.Version)
In DacFx 3.0 the DacStore is no longer available. To get the version from C# code you need to query the database. Here's an example:
using System;
using System.Data;
using System.Data.SqlClient;
class Program
{
static void Main()
{
try
{
string version = GetDatabaseVersion(#"Initial Catalog=xxx;Data Source=yyy;Integrated Security=True;Pooling=False", false);
Console.WriteLine("Database has DAC pack version {0}.", version);
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(ex.Message);
Console.WriteLine();
Console.ResetColor();
}
Console.WriteLine("Press any key to exit");
Console.ReadKey(true);
}
/// <summary>
/// Gets the database version.
/// </summary>
/// <param name="connectionString">The connection string of database to query.</param>
/// <param name="isAzure">True if we are querying an Azure database.</param>
/// <returns>DAC pack version</returns>
private static string GetDatabaseVersion(string connectionString, bool isAzure)
{
var connectionStringBuilder = new SqlConnectionStringBuilder(connectionString);
string instanceName = connectionStringBuilder.InitialCatalog;
string databaseToQuery = "msdb";
if (isAzure)
{
// On Azure we must be connected to the master database to query sysdac_instances
connectionStringBuilder.InitialCatalog = "Master";
databaseToQuery = "master";
}
string query = String.Format("select type_version from {0}.dbo.sysdac_instances WHERE instance_name = '{1}'", databaseToQuery, instanceName);
using (var connection = new SqlConnection(connectionStringBuilder.ConnectionString))
{
connection.Open();
SqlCommand command = connection.CreateCommand();
command.CommandText = query;
command.CommandTimeout = 15;
command.CommandType = CommandType.Text;
var version = (string)command.ExecuteScalar();
return version;
}
}
}

When is a started service not a started service? (SQL Express)

We require programmatic access to a SQL Server Express service as part of our application. Depending on what the user is trying to do, we may have to attach a database, detach a database, back one up, etc. Sometimes the service might not be started before we attempt these operations. So we need to ensure the service is started. Here is where we are running into problems. Apparently the ServiceController.WaitForStatus(ServiceControllerStatus.Running) returns prematurely for SQL Server Express. What is really puzzling is that the master database seems to be immediately available, but not other databases. Here is a console application to demonstrate what I am talking about:
namespace ServiceTest
{
using System;
using System.Data.SqlClient;
using System.Diagnostics;
using System.ServiceProcess;
using System.Threading;
class Program
{
private static readonly ServiceController controller = new ServiceController("MSSQL$SQLEXPRESS");
private static readonly Stopwatch stopWatch = new Stopwatch();
static void Main(string[] args)
{
stopWatch.Start();
EnsureStop();
Start();
OpenAndClose("master");
EnsureStop();
Start();
OpenAndClose("AdventureWorksLT");
Console.ReadLine();
}
private static void EnsureStop()
{
Console.WriteLine("EnsureStop enter, {0:N0}", stopWatch.ElapsedMilliseconds);
if (controller.Status != ServiceControllerStatus.Stopped)
{
controller.Stop();
controller.WaitForStatus(ServiceControllerStatus.Stopped);
Thread.Sleep(5000); // really, really make sure it stopped ... this has a problem too.
}
Console.WriteLine("EnsureStop exit, {0:N0}", stopWatch.ElapsedMilliseconds);
}
private static void Start()
{
Console.WriteLine("Start enter, {0:N0}", stopWatch.ElapsedMilliseconds);
controller.Start();
controller.WaitForStatus(ServiceControllerStatus.Running);
// Thread.Sleep(5000);
Console.WriteLine("Start exit, {0:N0}", stopWatch.ElapsedMilliseconds);
}
private static void OpenAndClose(string database)
{
Console.WriteLine("OpenAndClose enter, {0:N0}", stopWatch.ElapsedMilliseconds);
var connection = new SqlConnection(string.Format(#"Data Source=.\SQLEXPRESS;initial catalog={0};integrated security=SSPI", database));
connection.Open();
connection.Close();
Console.WriteLine("OpenAndClose exit, {0:N0}", stopWatch.ElapsedMilliseconds);
}
}
}
On my machine, this will consistently fail as written. Notice that the connection to "master" has no problems; only the connection to the other database. (You can reverse the order of the connections to verify this.) If you uncomment the Thread.Sleep in the Start() method, it will work fine.
Obviously I want to avoid an arbitrary Thread.Sleep(). Besides the rank code smell, what arbitary value would I put there? The only thing we can think of is to put some dummy connections to our target database in a while loop, catching the SqlException thrown and trying again until it works. But I'm thinking there must be a more elegant solution out there to know when the service is really ready to be used. Any ideas?
EDIT: Based on feedback provided below, I added a check on the status of the database. However, it is still failing. It looks like even the state is not reliable. Here is the function I am calling before OpenAndClose(string):
private static void WaitForOnline(string database)
{
Console.WriteLine("WaitForOnline start, {0:N0}", stopWatch.ElapsedMilliseconds);
using (var connection = new SqlConnection(string.Format(#"Data Source=.\SQLEXPRESS;initial catal
using (var command = connection.CreateCommand())
{
connection.Open();
try
{
command.CommandText = "SELECT [state] FROM sys.databases WHERE [name] = #DatabaseName";
command.Parameters.AddWithValue("#DatabaseName", database);
byte databaseState = (byte)command.ExecuteScalar();
Console.WriteLine("databaseState = {0}", databaseState);
while (databaseState != OnlineState)
{
Thread.Sleep(500);
databaseState = (byte)command.ExecuteScalar();
Console.WriteLine("databaseState = {0}", databaseState);
}
}
finally
{
connection.Close();
}
}
Console.WriteLine("WaitForOnline exit, {0:N0}", stopWatch.ElapsedMilliseconds);
}
I found another discussion dealing with a similar problem. Apparently the solution is to check the sys.database_files of the database in question. But that, of course, is a chicken-and-egg problem. Any other ideas?
Service start != database start.
Service is started when the SQL Server process is running and responded to the SCM that is 'alive'. After that the server will start putting user databases online. As part of this process, it runs the recovery process on each database, to ensure transactional consistency. Recovery of a database can last anywhere from microseconds to whole days, it depends on the ammount of log to be redone and the speed of the disk(s).
After the SCM returns that the service is running, you should connect to 'master' and check your database status in sys.databases. Only when the status is ONLINE can you proceed to open it.