I am trying to learn how to build a web service with WCF in .Net framework 4.5 using Visual Studio 2019, and I am trying to connect my service to a database already created which I want to do operation on through that web service, my exact question is: how to open a connection between the two things using SQlConnection class?, beacause I saw the constructors of the SqlConnection but I could't understand where can we write the address/Path of our database?
It may be a little bit stupid question, but I need a better explanasion than the one that exists on the Microsoft web site.
Here is my code, which describes a void method that creates the connection string. and then we call it every time we creat a connection.
Note: DataSource is the server address, IntitialCatalog is the database name
private void ConnectToDB(string datasource, string initialcatalog)
{
SqlConnectionStringBiulder ConnectionStringBuilder = new SqlConnectionStringBuilder()
{
DataSource = datasource,
InitialCatalog = initialcatalog,
IntegratedSecurity = true
};
SqlConnection connection = new SqlConnection(ConnectionStringBuilder.ToString());
SqlCommand command = connection.CreateCommand();
}
Obviously we can add the other available attributes to the connection string, and modify them as we want.
Related
I Have strange problem when i tried to publish my asp.net mvc application to my local (pc) iis with "Always Encrypted" Enabled.
My application keep timeout when i tried to access database using EF6 at local IIS (not express) :
But if i tried to access & debug my asp.net mvc app using Visual Studio 2017, database with 'always encrypted enabled' can be accessed perfectly without timeout.
And also i can access it with SQL Management Studio without problem.
Both (SMSS & ASP.NET web config) using this configuration.
Column Encryption Setting=enabled;
Note : I'm using ASP.NET MVC 5 & EF 6, SQL Server 2016 Developer Edition.
Sorry for my bad english.
UPDATED :
I have tried using .NET Framework Data Provider to see if there's any clue that'll help me solving this issue, Using following code :
var context = new TestDevEntities();
StringBuilder sb = new StringBuilder();
string connectionString = context.Database.Connection.ConnectionString;
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
using (SqlCommand cmd = new SqlCommand(#"SELECT [id],[name],[CCno] FROM [TestDev].[dbo].[testEncCol]", connection, null, SqlCommandColumnEncryptionSetting.ResultSetOnly))
{
using (SqlDataReader reader = cmd.ExecuteReader())
{
if (reader.HasRows)
{
while (reader.Read())
{
sb.Append(reader[2] + ";");
}
}
}
}
}
above code show me this error :
Now, with this kind of error i know i exactly i must do :)
Change the identity of application pool to the 'user' who previously generated the certificate.
Export currentuser cert (used by always encrypted) and import to the user that you want to use as application pool identity.
Now its worked!
EF should throw some kind of error as clear as .NET Data Providers do, instead of timeout failure that really confuse me #_#
UPDATED (1) :
Now the question is how to use it (Certificate) with default ApplicationPoolIdentity instead of custom account?
UPDATED (2) :
I have done what jakub suggest, but still no luck.
Thanks
One way (could be the only way) to use the DefaultAppPool identity instead of a custom (user) account is to store the certificate in the Local Machine certificate store (not Current User).
Once you create a certificate in the Local Machine certificate store, you need to grant DefaultAppPool access to the cert. You can do that using Microsoft Management Console (and the plugin for Local Computer certs):
Right click on the cert, select All Tasks > Manage Private Keys.
Click Add.
Set location to your computer (not your domain).
Enter IIS AppPool\DefaultAppPool as the object name.
Click OK twice.
im just new in ASP.net using MVC and my problem is im using two database, is there any posibility that i can use to get data of 1 st database and transfer it to another database? any help will be appreciated , even links
1) Using Entity Framework, create 2 classes that implement DBContext and use them to update the data.
2) Use Linq To Sql to create access the Databases and save your detail.
3)Just use simple ADO.NET to save the data.ps. change your connections string to match your required databases.
Try this below, using ADO.NET
using (SqlConnection connection = new SqlConnection("Integrated Security=SSPI;Initial Catalog=DB1"))
{
connection.Open();
// here you could read the data from DB1
}
using (SqlConnection connection = new SqlConnection("Integrated Security=SSPI;Initial Catalog=DB2"))
{
connection.Open();
// Write data to DB2 here
}
I have an application built using the ASP.NET 5 runtime - I would like to connect it to an on-premise SQL Server Database.
After some research I've already created the user-provided service with the relevant credentials, however I am unsure what to do next (i.e. writing the necessary code connecting it in ASP.NET).
Some further googling suggests to use Secure Gateway? but is this the only way? the cloud I am working on is dedicated and does not have the Secure Gateway service. Is there a workaround for this?
(Note: The application I'm working on is based on the ASP.NET-Cloudant example on IBM Github, if that helps).
https://github.com/IBM-Bluemix/asp.net5-cloudant
The Secure Gateway service isn't required as long as the Bluemix environment can connect to the server running SQL Server. This might require your firewall rules to be a little more relaxed on the SQL Server, or you can contact IBM to create a secure tunnel as Hobert suggested in his answer.
Aside from that issue, if you're planning to use Entity Framework to connect to your SQL Server, it should work similar to the existing tutorials on the asp.net site. The only difference will be in how you access the environment variables to create your connection string.
Assuming that you created your user-provided service with a command similar to this:
cf cups my-sql-server -p '{"server":"127.0.0.1","database":"MyDB","user":"sa","password":"my-password"}'
Your connection string in your Startup.cs file's ConfigureServices method would then look something like this:
string vcapServices = Environment.GetEnvironmentVariable("VCAP_SERVICES");
string connection = "";
if (vcapServices != null)
{
string myServiceName = "my-sql-server";
JArray userServices = (JArray)JObject.Parse(vcapServices)?["user-provided"];
dynamic creds = ((dynamic)userServices
.FirstOrDefault(m => ((dynamic)m).name == myServiceName))?.credentials;
connection = string.Format(#"Server={0};Database={1};User Id={2}; Password={3};",
creds.server, creds.database, creds.user, creds.password);
}
Update
The cloudant boilerplate that you're modifying doesn't use Entity Framework because cloudant is a NoSQL database, so it's a bit different than connecting to SQL Server. The reason that the boilerplate calls .Configure to register the creds class is that it needs to use that class from another location, but when using Entity Framework you simply need to use the credentials when adding EF to the services in the Startup.cs file so you don't need to use .Configure<creds>.
If you follow the guide here, the only part you'll need to change is the line var connection = #"Server=(localdb)\mssqllocaldb;Database=EFGetStarted.AspNet5.NewDb;Trusted_Connection=True;"; replacing it with the code above to create the connection string instead of hard-coding it like they did in the example tutorial.
Eventually, your ConfigureServices method should look something like this, assuming your DbContext class is named BloggingContext like in the example:
public void ConfigureServices(IServiceCollection services)
{
string vcapServices = Environment.GetEnvironmentVariable("VCAP_SERVICES");
string connection = "";
if (vcapServices != null)
{
string myServiceName = "my-sql-server";
JArray userServices = (JArray)JObject.Parse(vcapServices)?["user-provided"];
dynamic creds = ((dynamic)userServices
.FirstOrDefault(m => ((dynamic)m).name == myServiceName))?.credentials;
connection = string.Format(#"Server={0};Database={1};User Id={2}; Password={3};",
creds.server, creds.database, creds.user, creds.password);
}
services.AddEntityFramework()
.AddSqlServer()
.AddDbContext<BloggingContext>(options => options.UseSqlServer(connection));
services.AddMvc();
}
And then your Startup method would be simplified to:
public Startup(IHostingEnvironment env)
{
var configBuilder = new ConfigurationBuilder()
.AddJsonFile("config.json", optional: true);
Configuration = configBuilder.Build();
}
Excellent!
In Public Bluemix Regions, you would create and use the Secure Gateway Service to access the On-Premise MS SQL Server DB.
In your case, as a Bluemix Dedicated client, you should engage your IBM Bluemix Administration Team so they can work with your Network Team to create a tunnel between the Dedicated Bluemix Region and your On-Premise MS SQL DB Server.
If you want to connect directly from your Asp.Net Core application to a SQL Server you actually don't need a Secure Gateway.
For example, if you want to use a SQL Azure as your Database you can simply add the given connection string in your application.
But, for pratical and security reasons, you should create a User-Provided Service to store your credentials (and not use statically in your code), and pull your credentials from you VCAP_SERVICES simply adding SteelToe to your Cconfiguration Builder. (Instead of use parse the configuration manually with JObjects and JArrays)
Step-by-step:
In your CloudFoundry console create a User-Provided Service using a Json:
cf cups MySqlServerCredentials -p '{"server":"tcp:example.database.windows.net,1433", "database":"MyExampleDatabase", "user":"admin", "password":"password"}'
Obs.: If you use Windows console/Powershell you should escape you double quotes in Json like:
'{\"server\":\"myserver\",\"database\":\"mydatabase\",\"user\":\"admin\",\"password\":\"password\"}'
After you have created your User-Provided Service you should Connect this Service with your application in Bluemix Console.
Then, In your application add the reference to SteelToe CloudFoundry Steeltoe.Extensions.Configuration.CloudFoundry
In your Startup class add:
using Steeltoe.Extensions.Configuration;
...
var builder = new ConfigurationBuilder()
.SetBasePath(basePath)
.AddJsonFile("appsettings.json")
.AddCloudFoundry();
var config = builder.Build();
Finally, to access your configurations just use:
var mySqlName = config["vcap:services:user-provided:0:name"];
var database = config["vcap:services:user-provided:0:credentials:database"];
var server = config["vcap:services:user-provided:0:credentials:server"];
var password = config["vcap:services:user-provided:0:credentials:password"];
var user = config["vcap:services:user-provided:0:credentials:user"];
OBS.: If you're using Azure, remember to configure your Database firewall to accept the IP of your Bluemis application, but as default Bluemix don't give a static IP address you have some options:
Buy a Bluemix Statica service to you application (expensive)
Update firewall rules with REST put with the current IP of application (workaroud)
Open your Azure Database Firewall to a broad range of IPs. (Just DON'T)
More info about SteelToe CloudFoundry in :
https://github.com/SteeltoeOSS/Configuration/tree/master/src/Steeltoe.Extensions.Configuration.CloudFoundry
I know it looks like a duplicated since there are tons of questions regarding transactions on multiple contexts but none of them refer to this scenarios.
The setup
SQL Server 2016 (latest preview) on develop machine or SQL Azure v12 on production
Entity Framework 6.1.3
.Net 4.5 on a regular application
Application can run on an Azure Cloud Service or a VM, doesn't really matter
What we have in code
A single TransactionScope
Two DbContexts created outside the TransactionScope (it comes created by our dependency injection mechanics that are tied to ASP.Net MVC, so I left it out the scope for simplicity of the sample)
Each context create and maintain its own connection which points to different databases on different servers(it can also point to the same server in case of running on a development machine, but still different databases).
We use regular SQL Authentication - userId and password(just in case someone points to some post talking about problems with Integrated Security and MSDTC, we don't use it locally, since on Azure SQL it is not supported)
Our code sample
When we do something like:
var contextA = new ContextA();
var contextB = new ContextB();
using(var scope = new TransactionScope())
{
var objA = new EntityA();
objA.Name = "object a";
contextA.EntitiesA.Add(objA);
contextA.SaveChanges();
var objB = new EntityB();
objB.Name = "object B";
contextB.EntitiesB.Add(objB);
contextB.SaveChanges();
scope.Complete();
}
What we receive
A System.Data.Entity.Core.EntityException is thrown on the call of contextA.SaveChanges() with the following messages:
Root Exception: The underlying provider failed on EnlistTransaction.
Inner Exception: Connection currently has transaction enlisted. Finish current transaction and retry.
So, anyone have a clue on what exactly is going wrong with this sample?
We are trying to have a single transaction using multiple contexts and each context with its own connection to the database. Obviously since the data of each context is on different database servers(in production) we can't use the DbContext ctor that receives a DbConnection and shares it with both contexts, so share a DbConnection is not an option.
Thank you very much, I really appreciate any help.
Distributed transactions with TransactionScope are now supported by Azure SQL Database. See TransactionScope() in Sql Azure.
AFAIK, distributed transactions are not supported in SQL Azure. Source
I have to write a small C# program which will handle at least three differents database vendors (Oracle, Sybase ASE, SqlServer) in a dynamic way. (It will rely on customer choices to choose the database)
I decided to use "pure" managed drivers through ado.net data providers.
But, when I just try connecting, I expected code a la "One line to rule them all", just like JDBC does with :
DriverManager.getConnection(connection_string);
Instead of this, surprised, I have to write for each driver its specific code :
SqlConnection() for SqlServer
AseConnection() for Sybase
OracleConnection(), etc.
Of course, I should encapsulate -by myself- all of this inside abstract methods and dynamic loadings, but I'm wondering why such a thing doesn't already exist in .net
Mmhhh, I've got the feeling that I'm missing something
Since you have the .Net Provider for he respective database installed on the machine, you can use the DbProviderFactory, for sample:
include
using System.Data.Common;
and try something like this:
// create the provider factory from the namespace provider
DbProviderFactory factory = DbProviderFactories.GetFactory("System.Data.SqlClient");
// you could create any other provider factory.. for Oracle, MySql, etc...
// use the factory object to create Data access objects.
DbConnection connection = factory.CreateConnection(); // will return the connection object, in this case, SqlConnection ...
connection.ConnectionString = "read connection string from somewhere.. .config file for sample";
try
{
// open connection
connection.Open();
// create command to execute queries...
DbCommand command = connection.CreateCommand(); // create a SqlCommand, OracleCommand etc... depende of the provider factory configured.
// some logic
}
catch
{
}
finally
{
// close connection
connection.Close();
}
To know, what providers your application can find, you can use the DbProviderFactories.GetFactoryClasses() method to get a DataTable with details of every provider installed on the machine.