Create Connection String during installation - vb.net

I have a Windows Forms application. I want to create a setup file for this application. I used Visual Studio 2012 and SQL Server 12.
I want this setup to work in every new environment.
So, how do I make this connection string dynamic? Can I create a connection string after installation and make it available for every form to access, like in my local machine?
Any kind of source code, video links, explanations or examples will be a great help for me.

I propose to search on the machine for instances of the SQL server, and then in every instance search for the databases. You could setup some logic for example if only one instance is found, and on this instance only database with specific name exists then use this database, but if two or more instances are found, or different database name then preferred is found, show window to user where he can choose the right one.
To find Database instance you could use following method:
private static DataRowCollection SQLDataServers()
{
System.Data.Sql.SqlDataSourceEnumerator instance = System.Data.Sql.SqlDataSourceEnumerator.Instance;
DataTable dt = instance.GetDataSources();
if (dt.Rows.Count>0)
{
return dt.Rows;
}
throw new Exception("No SQL Instance Found");
}
To find tables in the database you can use following method:
private static List<string> GetDatabases(string conString)
{
List<string> list = new List<string>();
using (SqlConnection con = new SqlConnection(conString))
{
con.Open();
using (SqlCommand cmd = new SqlCommand("SELECT name from sys.databases", con))
{
using (IDataReader dr = cmd.ExecuteReader())
{
while (dr.Read())
{
list.Add(dr[0].ToString());
}
}
}
}
return list;
}
To generate connection string you can use nuget package or following methods:
public static string GetSqlDataSourceConnectionString(string dataSource)
{
return GetSQLDataSource(dataSource).ToString();
}
private static SqlConnectionStringBuilder GetSQLDataSource(string dataSource)
{
var r = GetDataSource(dataSource).AddIntegratedSecurity();
return r;
}
private static SqlConnectionStringBuilder GetDataSource(string dataSource)
{
SqlConnectionStringBuilder sqlBuilder = new
SqlConnectionStringBuilder();
sqlBuilder.DataSource = dataSource;
return sqlBuilder;
}
private static SqlConnectionStringBuilder AddIntegratedSecurity(this SqlConnectionStringBuilder connectionStringBuilder)
{
connectionStringBuilder.IntegratedSecurity = true;
return connectionStringBuilder;
}
The method which connects all this elements can be as following:
static void Main(string[] args)
{
var servers=SQLDataServers();
foreach (DataRow item in servers)
{
string serverName = string.Format($"{item.ItemArray[0].ToString()}\\{item.ItemArray[1].ToString()}");
var connectionString = GetSqlDataSourceConnectionString(serverName);
var listOfDB=GetDatabases(connectionString);
}
}

Related

Unable to connect Azure Function App with Database (using .net core 2.1)

Please note (Environment):
Function App: Version 2,
Target Framework: .Net Core 2.1
I am developing a Function App, that will work like Web Api. This Function App will return the data from database tables, also it'll manipulate files in Azure storage(Blob). But I am stuck as I am unable to create ConnectionString from local.settings.json file. Ideally the connection string should be created by default as I followed some tutorials & no where mentioned any extra steps to create default connectionstring value, just need to create it in local.settings.json file.
following is my local.settings.json file content:-
{
"ConnectionStrings": {
"mycs": "data source=servername;initial catalog=dbname;user id=XXXX;password=XXXX;MultipleActiveResultSets=True;"
},
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"mycs": "data source=servername;initial catalog=dbname;user id=XXXX;password=XXXX;MultipleActiveResultSets=True;"
}
}
following is my HttpTrigger file:
namespace my_api
{
public class myDataContext : DbContext
{
public myDataContext() : base(GetConnectionString()) { }
private static string GetConnectionString()
{
const string providerName = "System.Data.SqlClient";
const string metadata = #"res://*/MYDB.csdl|res://*/MYDB.ssdl|res://*/MYDB.msl";
try
{
string connectString = ConfigurationManager.ConnectionStrings["mycs"].ToString();
// Initialize the connection string builder for the
// underlying provider.
SqlConnectionStringBuilder sqlBuilder = new SqlConnectionStringBuilder(connectString);
// Set the properties for the data source.
//sqlBuilder.IntegratedSecurity = true;
sqlBuilder.MultipleActiveResultSets = true;
// Build the SqlConnection connection string.
string providerString = sqlBuilder.ToString();
// Initialize the EntityConnectionStringBuilder.
EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
//Set the provider name.
entityBuilder.Provider = providerName;
// Set the provider-specific connection string.
entityBuilder.ProviderConnectionString = providerString;
// Set the Metadata location.
entityBuilder.Metadata = metadata;
return entityBuilder.ConnectionString;
}
catch { }
var connectionstring = Environment.GetEnvironmentVariable("mycs");
return connectionstring;
}
public DbSet<flowerset> flowersets
{
get;
set;
}
}
}
Following is the code for :
namespace my_api
{
public static class helpService
{
[FunctionName("helpService_get")]
public static async Task> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequest req,
ILogger log, ExecutionContext context)
{
log.LogInformation("C# HTTP trigger function processed a request helpService_get).");
try {
int page = 0;
int pageSize = 20;
myDataContext entity = new myDataContext();
if (page == 0 && pageSize == 0)
{
return entity.helpsets.ToList();
}
if (pageSize <= 0) { pageSize = 20; }
entity.helpsets.OrderByDescending(x => x.id).Skip((page - 1) * pageSize).Take(pageSize).ToList();
}
catch (Exception exx) {
log.LogInformation("Exception changed (helpService_get): "+exx.Message);
}
return null;
}
}//End of Class
}//End of Namespace
I am getting following error on line entity.helpsets.OrderByDescending(x => x.id).Skip((page - 1) * pageSize).Take(pageSize).ToList();:
Unable to determine the provider name for provider factory of type 'System.Data.SqlClient.SqlClientFactory'. Make sure that the ADO.NET provider is installed or registered in the application config.
According to my test, we can use System.Data.SqlClient to connect Azure SQL in Azure function V2.0. For example
Create an Azure Function with Visual Studio 2019
Install System.Data.SqlClient package(the version I sue is 4.5.1)
Develop the function
local.settings.json file content
"ConnectionStrings": {
"mycs": "Data Source="";Initial Catalog=DotNetAppSqlDb20190826105048_db;User Id="";Password="" "
},
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "dotnet"
}
}
Code
[FunctionName("Function1")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string name = req.Query["name"];
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;
try
{
var connectionstring = System.Environment.GetEnvironmentVariable($"ConnectionStrings:mycs"); ;
using (SqlConnection connection = new SqlConnection(connectionstring))
{
connection.Open();
log.LogInformation(" sql login success");
StringBuilder sb = new StringBuilder();
sb.Append("select * from dbo.Todoes");
String sql = sb.ToString();
using (SqlCommand command = new SqlCommand(sql, connection))
{
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
log.LogInformation("{0} {1}", reader.GetInt32(0), reader.GetString(1));
}
}
}
connection.Close();
}
}
catch (SqlException e)
{
Console.WriteLine(e.ToString());
}
return name != null
? (ActionResult)new OkObjectResult($"Hello, {name}")
: new BadRequestObjectResult("Please pass a name on the query string or in the request body");
}
For more details, please refer to the document

Using SQL Dependency with Azure

In my Local DB Sql Dependency works fine, but when i migrate to an Azure Database is not work.
I check if service broker is enabled, and it is activated.
This is the error:
Statement 'RECEIVE MSG' is not supported in this version of SQL Server
This is my code:
public class Program
{
static void Main(string[] args)
{
SqlClientPermission permission = new SqlClientPermission(System.Security.Permissions.PermissionState.Unrestricted);
if (SolicitarNotifications())
{
string con = "Server=tcp:xxxxx.database.windows.net,0000;Initial Catalog=TestSQLDependendcy;Persist Security Info=False;User ID=xxxx;Password=xxxxx;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;";
SqlConnection conn = new SqlConnection(con);
SqlDependency.Start(con);
Console.WriteLine("Empezando a escuchar");
GetAlerts();
Console.WriteLine("Presiona enter para salir");
Console.ReadLine();
Console.WriteLine("Deteniendo la escucha...");
SqlDependency.Stop(con);
}
else {
Console.WriteLine("No tienes permitido solicitar notificaciones");
}
}
public static void GetAlerts()
{
try
{
using (SqlConnection con = new SqlConnection("Server=tcp:xxxxx.database.windows.net,0000;Initial Catalog=TestSQLDependendcy;Persist Security Info=False;User ID={your_username};Password={your_password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"))
{
SqlCommand cmd = new SqlCommand("Select Correo, Nombre From TestNombre", con);
cmd.CommandType = CommandType.Text;
cmd.Notification = null;
cmd.Dispose();
SqlDependency dependency = new SqlDependency(cmd);
dependency.OnChange += new OnChangeEventHandler(OnDataChange);
con.Open();
SqlDataReader dr = cmd.ExecuteReader();
{
while (dr.Read())
{
if (dr.HasRows)
{
using (MailMessage mm = new MailMessage())
{
//Send Mails
}
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message.ToString());
}
}
private static void OnDataChange(object sender, SqlNotificationEventArgs e)
{
SqlDependency dependency = sender as SqlDependency;
dependency.OnChange -= new OnChangeEventHandler(OnDataChange);
GetAlerts();
}
}
How to run this service in Azure SQL Database?
Currently, Azure SQL does not support Service Broker.
Find RECEIVE statement supported versions at https://learn.microsoft.com/en-us/sql/t-sql/statements/receive-transact-sql?view=sql-server-2017, which states Azure SQL does not support it.
In addition, this documentation https://learn.microsoft.com/en-us/azure/sql-database/sql-database-features provides a great feature comparison documentation between SQL Server, Azure SQL and Managed Instances. Note that Manage Instance supports Service Broker with some differences. I'd recommend signing up for the preview and trying it out.

Could not GetActiveTransaction

I need to call stored procedure in my App Service. I'm following this tutorial to create a custom repository. But I could not find the Context.Database.
Here is the code:
[UnitOfWork]
public virtual async Task<List<string>> GetUserNames()
{
EnsureConnectionOpen();
using (var command = CreateCommand("GetUsernames", CommandType.storedProcedure))
{
using (var dataReader = await command.ExecuteReaderAsync())
{
var result = new List<string>();
while (dataReader.Read())
{
result.Add(dataReader["UserName"].ToString());
}
return result;
}
}
}
What is the Context.Database and how do I use it?
My application is MVC in .Net4.6.1.
Update 1
I have resolved this issue by inheriting MyApplicationRepositoryBase.
Now I face a new issue when trying to GetActiveTransaction. I don't have any idea about this. What can I do?
Here is the code:
private DbTransaction GetActiveTransaction()
{
return (DbTransaction)_transactionProvider.GetActiveTransaction(new ActiveTransactionProviderArgs
{
{"ContextType", typeof(MyDbContext) },
{"MultiTenancySide", MultiTenancySide }
});
}
Here is the error log:
System.NullReferenceException: Object reference not set to an instance of an object.
at Abp.EntityFramework.EfActiveTransactionProvider.GetActiveTransaction(ActiveTransactionProviderArgs args) in D:\Github\aspnetboilerplate\src\Abp.EntityFramework\EntityFramework\EfActiveTransactionProvider.cs:line 21
Update 2
I tried to comment out the command.Transaction and it worked:
private DbCommand CreateCommand(string commandText, CommandType commandType, params SqlParameter[] parameters)
{
var command = Context.Database.GetDbConnection().CreateCommand();
command.CommandText = commandText;
command.CommandType = commandType;
// command.Transaction = GetActiveTransaction();
foreach (var parameter in parameters)
{
command.Parameters.Add(parameter);
}
return command;
}
I still need to put my code under a Transaction, so I don't want to comment out this line. What should I do?
Now I faced the new issue when trying to get Active Transaction
Add this in PreInitialize method of YourProjectNameDataModule:
Configuration.ReplaceService<IEfTransactionStrategy, DbContextEfTransactionStrategy>(DependencyLifeStyle.Transien‌​t);

Changing Performance point data source connections programmatically

I have many reports in PPS which has around 60 data sources to analysis services. I want to change their connection string (i.e. I want to change the server which they are pointing to). I have tried below solution (Console application) to get the list of data sources available in SharePoint for PPS but can't see/modify connection strings.
static void Main(string[] args)
{
DataTable dt = new DataTable();
dt = GetList("SharePoint site URL", "Data Connections");
}
public static DataTable GetList(string site, string listname)
{
ClientContext ctx = new ClientContext(site);
List lst = ctx.Web.Lists.GetByTitle(listname);
CamlQuery cq = CamlQuery.CreateAllItemsQuery();
ListItemCollection lic = lst.GetItems(cq);
ctx.Load(lic);
ctx.ExecuteQuery();
DataTable dt = new DataTable();
foreach (var field in lic[0].FieldValues.Keys)
{
dt.Columns.Add(field);
}
foreach (var item in lic)
{
DataRow dr = dt.NewRow();
foreach (var obj in item.FieldValues)
{
if (obj.Value != null)
{
string type = obj.Value.GetType().FullName;
if (type == "Microsoft.SharePoint.Client.FieldLookupValue")
{
dr[obj.Key] = ((FieldLookupValue)obj.Value).LookupValue;
}
else if (type == "Microsoft.SharePoint.Client.FieldUserValue")
{
dr[obj.Key] = ((FieldUserValue)obj.Value).LookupValue;
}
else
{
dr[obj.Key] = obj.Value;
}
}
else
{
dr[obj.Key] = null;
}
}
dt.Rows.Add(dr);
}
return dt;
}
With above code I am getting all data connections available in "Data Connections" list (below screenshot is the data table structure)
Unfortunately, there is no connection string in that information. I am not able to find any solution online.

NHibernate 3.2: SchemaExport not working with SQLite

I'm using an in-memory db for some quick unit tests, using the following code:
public class MemoryDb
{
private static Configuration configuration;
private static ISessionFactory sessionFactory;
static MemoryDb()
{
configuration = new NHibernate.Cfg.Configuration();
configuration.DataBaseIntegration(x =>
{
x.Driver<SQLite20Driver>();
x.Dialect<SQLiteDialect>();
x.ConnectionProvider<DriverConnectionProvider>();
x.KeywordsAutoImport = Hbm2DDLKeyWords.AutoQuote;
x.IsolationLevel = IsolationLevel.ReadCommitted;
x.ConnectionString = "Data Source=:memory:;";
x.Timeout = 255;
x.BatchSize = 100;
x.LogFormattedSql = true;
x.LogSqlInConsole = true;
x.AutoCommentSql = false;
});
configuration.AddMapping(DbHelper.GetAutoMappings());
sessionFactory = configuration.BuildSessionFactory();
}
public static ISession GetSession()
{
var session = sessionFactory.OpenSession();
new SchemaExport(configuration).Execute(true, true, false, session.Connection, null);
return session;
}
}
The problem is that the schema export doesn't seem to be working. On of my tests looks like this:
[Fact]
public void ShouldFindDuplicateByEmail()
{
using (var session = MemoryDb.GetSession())
{
var repo = new NHibernateCustomerRepository(session);
var customer = new Customer();
customer.EmailAddress = "test#test.com";
repo.Save(customer);
var duplicates = repo.FindDuplicates(customer);
Assert.Equal(1, duplicates.Length);
}
}
The test fails with the error no such table: Customers. This all worked with Fluent NHibernate and NHibernate 3.1. I know it's not an issue with the mappings themselves, because the actual application works when I run it against an existing SQL Server db. It only fails when running the tests. Any thoughts?
Edit: If I change only the connection string such that it writes to a file (i.e. x.ConnectionString = "data source=" + Path.GetTempFileName();, the whole thing works. I'm guessing either the schema isn't run correctly against the in-memory db, or it's getting a new in-memory db each time I execute a session command, but have no clue how to figure this out.
I found the answer here: https://forum.hibernate.org/viewtopic.php?p=2397541#p2397541
I had to add the following to the db configuration:
x.ConnectionReleaseMode = ConnectionReleaseMode.OnClose;
Otherwise, NHibernate releases the connection after each statement is flushed, thereby getting rid of the in-memory database with the schema.