DB connection strings in MVC applications using Entity Framework - sql-server

I am working on an MVC application using Entity Framework.
After creating an EDMX, I noticed the DB connection string is located in TWO places - an app.config file in my Data class library, and a web.config file in my web application.
We want to:
remove these two plain text connection strings
encrypt a single connection string
and use our pre-existing class library to decrypt the connection string when needed
I tried removing one or the other connection string from the config files, and DB access fails. Why are TWO required? And is there any way to do what we want in an MVC - EF project, and how would I tell EF that is what we are doing?
Thanks!

You can ignore the connection string in your EF project, I think, and just set the connection programmatically from your controller.
public class SomeController : Controller
{
public SomeController()
{
/* Substitute whatever method you want to fetch your data source string here */
/* example assumes plain text from web.config */
string dataSource = ConfigurationManager
.ConnectionStrings["ApplicationServices"]
.ConnectionString;
this.Entities = new SomeEntities(dataSource);
}
private SomeEntities Entities { get; set; }
}

Related

Xamarin Forms - How do i use a Premade Local Database? [Solved] [duplicate]

I have started using the Xamarin plugin for Visual Studio to create an Android app.
I have a local SQL database, and I want to call it to display data. I don't see how I can do this. Is it possible?
After thinking this was a trivial thing to do, I was proven wrong when I tried setup a quick test project. This post will contain a full tutorial on setting up a DB for an Android App in Xamarin that will come in handy as a reference for future Xamarin users.
At a glance:
Add Sqlite.cs to your project.
Add your database file as an Asset.
Set your database file to build as an AndroidAsset.
Manually copy the database file out of your apk to another directory.
Open a database connetion using Sqlite.SqliteConnection.
Operate on the database using Sqlite.
Setting up a local database for a Xamarin Android project
1. Add Sqlite.cs to your project.
Start by going to this repository and downloading Sqlite.cs; this provides the Sqlite API that you can use to run queries against your db. Add the file to your project as a source file.
2. Add DB as asset.
Next, get your DB and copy it into the Assets directory of your Android project and then import it into your project so that it appears beneath the Assets folder within your solution:
I'm using the Chinook_Sqlite.sqlite database sample renamed to db.sqlite from this site throughout this example.
3. Set DB to build as AndroidAsset.
Right click on the DB file and set it to build action AndroidAsset. This will ensure that it is included into the assets directory of the APK.
4. Manually copy DB out of your APK.
As the DB is included as an Asset (packaged within the APK) you will need to extract it out.
You can do this with the following code:
string dbName = "db.sqlite";
string dbPath = Path.Combine (Android.OS.Environment.ExternalStorageDirectory.ToString (), dbName);
// Check if your DB has already been extracted.
if (!File.Exists(dbPath))
{
using (BinaryReader br = new BinaryReader(Android.App.Application.Context.Assets.Open(dbName)))
{
using (BinaryWriter bw = new BinaryWriter(new FileStream(dbPath, FileMode.Create)))
{
byte[] buffer = new byte[2048];
int len = 0;
while ((len = br.Read(buffer, 0, buffer.Length)) > 0)
{
bw.Write (buffer, 0, len);
}
}
}
}
This extracts the DB as a binary file from the APK and places it into the system external storage path. Realistically the DB can go wherever you want, I've just chosen to stick it here.
I also read that Android has a databases folder that will store databases directly; I couldn't get it to work so I've just ran with this method of using an existing DB.
5. Open DB Connection.
Now open a connection to the DB through the Sqlite.SqliteConnection class:
using (var conn = new SQLite.SQLiteConnection(dbPath))
{
// Do stuff here...
}
6. Operate on DB.
Lastly, as Sqlite.net is an ORM, you can operate on the database using your own data types:
public class Album
{
[PrimaryKey, AutoIncrement]
public int AlbumId { get; set; }
public string Title { get; set; }
public int ArtistId { get; set; }
}
// Other code...
using (var conn = new SQLite.SQLiteConnection(dbPath))
{
var cmd = new SQLite.SQLiteCommand (conn);
cmd.CommandText = "select * from Album";
var r = cmd.ExecuteQuery<Album> ();
Console.Write (r);
}
Summary
And that's how to add an existing Sqlite database to your Xamarin solution for Android! For more information check out the examples included with the Sqlite.net library, its unit tests and the examples in the Xamarin documentation.
Here is the one that I'm using and it's working
install the Sqlite plugin
create interface to access different platforms services
create a model for the table
implement the interface that you created earlier on all of the
platform you want to use
use the plugin to create, get, insert, etc on your table
for more detailed information check this

Change SQL Server Connection String Dynamically inside an ASP.Net Core application

I open one database at the start, then need to open another database based on user selecting two values. The database selection has to be at run-time and will change every time.
Have tried to access the Connection String using the Connection String class and have tried other options like Singleton which I do not understand. I am running this on a local Windows 10 system running SQL Server Express. Am coding using Asp.Net Core 2.1
> ASP.Net Core v2.1
Building multi tenant, multi year application
Every client will have one SQL DATABASE per year
I hope to have a table with the following structure
COMPANY_CODE VARCHAR(3),
COMPANY_YEAR INT,
COMPANY_DBNAME VARCHAR(5)
Sample Data
COMPANY_CODE: AAD
COMPANY_YEAR: 19
COMPANY_DB: AAD19
COMPANY_CODE: AAD
COMPANY_YEAR: 18
COMPANY_DB: AAD18
COMPANY_CODE: AAD
COMPANY_YEAR: 17
COMPANY_DB: AAD17
So, every company will multiple rows - one for each financial year.
The COMPANY_DB column will store the DB name to open for that session.
Once the user is authenticated, I want to change the connection string to point to the database in the COMPANY_DB column of the selected row and then let the logged in user perform transactions.
I am unable to figure out how to change the connection string that is embedded in startup.cs.
Any tips on how to achieve this will be most appreciated.
I figured out that you are using one DbContext class for each database. See here for more information: docs.
Remove AddDbContext from Startup, remove OnConfiguring from DbContext and pass options to the constructor.
public class BloggingContext : DbContext
{
public BloggingContext(DbContextOptions<BloggingContext> options)
: base(options)
{ }
public DbSet<Blog> Blogs { get; set; }
}
Then, write service providing DbContext:
public interface IBlogContextProvider
{
BlogContext GetBlogContext(string connectionString);
}
public class BlogContextProvider : IBlogContextProvider
{
BlogContext GetBlogContext(string connectionString)
{
var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
optionsBuilder.UseSqlServer(connectionString);
return new BlogContext(optionsBuilder);
}
}
Add service in your Startup.cs:
services.AddScoped<IBlogContextProvider, BlogContextProvider>();
Now you can use DI:
public class HomeController : Controller
{
private IBlogContextProvider _provider;
public HomeController(IBlogContextProvider provider)
{
_provider = provider;
}
public ActionResult Index()
{
using (var context = _provider.GetBlogContext(<your connection string>))
{
//your code here
}
return View();
}
}
EDIT: Of course, you can write ContextProvider as generic.

Code first migrations database error

I used this pluralsight video on MVC code first migrations to keep my default MVC IdentityDb context and create another context for custom tables. Since then I get an error trying to connect connecting to the database online:
CREATE DATABASE permission denied in database 'master'.
.........
It works locally. My connection string are correct and my context classes point to the right connection string name:
public class IdentityDb : IdentityDbContext<ApplicationUser>
{
public IdentityDb()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static IdentityDb Create()
{
return new IdentityDb();
}
}
public class CustomDb : DbContext
{
public CustomDb() : base("DefaultConnection") { }
public DbSet<Inquiry> Inquiry { get; set; }
public DbSet<Product> Product { get; set; }
}
Connection string:
<add name="DefaultConnection" connectionString="server=***.db.1and1.com; initial catalog=***;uid=***;pwd=***" providerName="System.Data.SqlClient" />
I've read that the connection string name should be the same as the context class name but since I have two contexts I need a common name (DefaultConnection) which I've specified in the contexts.
It works connecting to my local database but not when its online so I did wonder if this would relate to the migration history table being up to date online and EF 6 trying to update the database but the entries in the migrations table match.
Any help appreciated.
* UPDATE *
I tried resetting the EF migrations with this guide thinking if the migrations where out of sync with the online DB it could result in EF trying to re-create the database causing this issue. However the problem still persists!
I have now added these lines to my context constructors respectively:
Database.SetInitializer<IdentityDb>(null);
Database.SetInitializer<CustomDb>(null);
This has stopped the error but kind of defeated the purpose of EF because I now have to remove it when creating migrations and manually script the changes to the online DB, then put it back in for the site to work online.

Using the same class library in windows application and web service

I working with:
Class Library: Model.dll
using System;
using System.Collections.Generic;
using System.Text;
namespace root
{
public class Customer
{
private int _Id;
public int Id
{
get { return _Id; }
set { _Id = value; }
}
private string _Name;
public string Name
{
get { return _Name; }
set { _Name = value; }
}
}
}
ASP.NET Web Service with reference to Model.dll so i can use in web method:
[WebMethod]
public string HelloWorld(root.Customer customer) {
return "Hello World";
}
Windows Application with reference to both Model.dll and Web Service (1).
root.Customer newCustomer = new Customer();
newCustomer.Id = 1;
newCustomer.Name = "Name";
ws.Service ws = new root.ws.Service();
ws.HelloWorld(newCustomer);
^ problem here
Error: Argument '1': cannot convert from 'root.Customer' to 'root.ws.Customer'
(1) Right click -> And Web Reference -> Web services in this solution -> Click Service.asmx ->
Enter Web reference name: ws -> Click Add reference
Updated: I can change line in generated Reference.cs file from
public string HelloWorld(Customer customer)
to
public string HelloWorld(root.Customer customer)
So function will be looking for real model instead of proxy object, but is not real answer.
I don't event think about editing this file after each web reference update.
How to force this for using real model?
I am afraid that reusing types in automatically generated ASMX proxies is impossible.
There are three options.
1) write your own code generator that will act like the wsdl.exe i.e. build a proxy of your web service but reusing your specified types
(rather difficult)
2) write your own code rewriter that will rewrite proxies generated automatically to use your own types. You'd invoke such rewriter each time after you build up your reference to the web service
(still tedious)
3) switch to WCF web services. a WCF service on a basicHttpBinding is semantically equivalent to a ASMX web service (uses the same communication protocol based on http + soap) but the WCF service metadata contain more information about types so that the proxy generator is able to "reuse types from referenced assemblies".
(suggested approach)
If you switch away from asmx and start using WCF's svc model, you can share a library between the server and client without much fuss at all. If that is an option, there are plenty of resources to help you out with WCF online.

Runtime dynamic SQL Server database access by different connection strings

I've searched the stackoverflow for a long time and didn't find a solution fit my situation, so I asked here.
I have a single asp.net website, and need the web app to access different SQL Server database by the subdomain name.
According to the url request subdomian to determine the access the different database.
prj1.test.com prj1--->use the prj1_DB
prj2.test.com prj2 use the prj2_DB
I couldn't find a better practice to solve the issue.
My intuition solution:
when the url request coming, get the url subdomain, get the subdomain's db connection string stored in the main db, passing the connection string to the DAL to get the data.
Index.aspx.cs
DataTable dt = ProjectObject.GetProjectIndexNotice(new object[] { 0, CurrentProject.DbConnectionString });
ProjectObject.cs
public static DataTable GetProjectIndexNotice(object[] param)
{
ProjectDLC obj = new ProjectDLC();
return obj.GetProjectIndexNotice(param);
}
ProjectDAL.cs
public DataTable GetProjectIndexNotice(object[] param)
{
return base.GetDataTableFromDatabase(param, "NEMP_GetProjectIndexNotice");
}
DALBase.cs
DataBase db = new Microsoft.Practices.EnterpriseLibrary.Data.Sql.SqlDatabase(CurrentProject.DbConnectionString);
I want to find a better way to solve this problem.
The solution I using above is:
get the dbConnectionString from main DB,
passing it over the Index.page ->BusinessObject Layer -->DAL Layer
It's so bad that passing the DB connection string from UI page to the DAL layer.
Any ideas?
Update 1:
What I really want is: don't pass the db connection string from UI to DAL layer.
I want to find a solution that don't do pass the db connstr from UI to DAL linearly.
Is there some pattern in asp.net to share some variable for UI layer and DAL Layer?
Update 2:
if I stored the project db info in a xml file or in the main db, it looks like this
it's a key-value part for the project. here is the question, I get the values all in the main DB or a xml file. How I get the key when I need to access the DB in DAL layer?
in the DAL layer, how to get the correct key for the currnet url request?
it's back to the above, pass the key from UI to DAL. that's I want to avoid.
the real problem is, I can get the key from url request in the UI layer, and I can get the value for that key in the DAL layer. but there is a gap between the two layers, How to conquer this gap?
If you can compute your connection string from a base connection string, then you could do something like this:
store the base connection string in your web.config
<connectionStrings>
<add name="BaseConnString"
connectionString="server=MyServer;database=master;Integrated Security=SSPI;" />
</connectionStrings>
load the base connection string into a SqlConnectionStringBuilder in your code:
string baseConnStr = WebConfigurationManager.ConnectionString["BaseConnString"].ConnectionString;
SqlConnectionStringBuilder scsBuilder =
new SqlConnectionStringBuilder(baseConnStr);
now, just define the database you want to connect to, e.g. based on something in your URL
scsBuilder.InitialCatalog = "ProjectDatabase" + ........ ;
use the resulting complete connection string for your SqlConnection:
using(SqlConnection _con = new SqlConnection(scsBuilder.ConnectionString))
{
// do something
}
Check out the MSDN docs on SqlConnectionStringBuilder.
With this approach, you'd store a single "base" connection string in your web.config and this wouldn't be changing, and using SqlConnectionStringBuilder, you can safely and efficiently define and "compute" your real, "dynamic" connection strings at runtime.
How about adding add the connection strings in web.config as:
Subdomain_connectionString
Now read the subdomain from Request:
Reading connection string from web.config in your DL:
ConfigurationManager.ConnectionStrings[Subdomain_connectionString].ConnectionString
Update:
You can also use xml files to store connection string values:
<ROOT>
<Project_1>
<IPAddress></IPAddress>
<DBName></DBName>
...
</Project_1>
<Project_2>
....
</ROOT>
Anytime a new project is added/removed this xml file would be updated. Use XPath expressions to parse the xml file.
#Passing Connection string from UI to DAL: Just try to add the System.web namespace to DAL layer. This would give access to Request object in DAL. Now you can get the subdomain and build the connectionstring in DAL itself. Not sure whether this is a right approach, but might work in your case.

Resources