0

I have a Web API with 3 tier architecture as shown below:

PresentationLayer (in the presentation layer i have appsetting.json where the connection string is)

BusinessLayer (Class library)

DataLayer (class library)

When I was still using .Net Framework I used to do in the dataLayer this code shown in the link below to get the connection string from the web.config of the presentation layer:

enter image description here

Now days I am experimenting with .Net Core 2.1 and i have build the same class in the data layer but it is not working. how can I pass the connection string from the presentation layer to the data layer most efficient way. Is there a similar way how i used to pass the connection string when i was working with .Net framework.

Can you help me please.

Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
Whiplash
  • 93
  • 1
  • 10
  • 2
    Please do not post screenshots of your code, copy/paste your source code as text instead. – Rui Jarimba Oct 02 '18 at 19:13
  • I don't think if it's a good practice to pass connection string from PL to DL. – Sham Oct 02 '18 at 19:15
  • 1
    Are you not using Entity Framework? If not, I recommend you look at it. At the very least though, go and learn about dependency injection. – DavidG Oct 02 '18 at 19:15
  • @DavidG no I don't want to use Entity framework. And by Dependency injection you mean create an appsettings.json in the datalayer? – Whiplash Oct 02 '18 at 19:21
  • If I had to go back to using ADO.Net directly, I would hurt someone. There's really almost no need to avoid using it (or another ORM). Anyway.... no, that's not what DI is at all, you absolutely need to go do your research. – DavidG Oct 02 '18 at 19:25
  • @DavidG no i am not using ADO.NET directly i am using Stored procedures etc etc – Whiplash Oct 02 '18 at 19:28
  • Well, you're using ADO.Net to call stored procs, which EF can also do and put the data into nice objects too. – DavidG Oct 02 '18 at 19:29
  • @DavidG is there something wrong that i am using ADO.NET instead EF i agree with you the EF is cleaner and fast way to build and structure code but i still prefer ADO.NET. By d way when i am build large projects i prefer to use ADO.NET for performance reasons. may be i'm wrong but any way – Whiplash Oct 02 '18 at 19:43
  • @Whiplash no matter the platform, the presentation layer has no business knowing about connection strings. That held even back in the VB6 days. In any case, what you call "3-tier" isn't. It's 3 layers that are actually baked into the Web API-MVC architecture, as the View, Controller and Model. – Panagiotis Kanavos Oct 03 '18 at 06:25
  • @Whiplash btw that class is a bad example and the wrong way to use connections. ADO.NET *already* [abstracts connection classes and provides db agnostic factory methods](https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/factory-model-overview), while the `using` block ensures connections are always closed when needed. This class breaks both the abstraction and safe disposal/closing. All you really need is a way to get the connection string from settings – Panagiotis Kanavos Oct 03 '18 at 06:29
  • @PanagiotisKanavos 1. can you please explain better your last comment. 2. can you explain why that class that is used for to get connection string is wrong? – Whiplash Oct 03 '18 at 11:12
  • @PanagiotisKanavos by the first comment you posted so you are saying creating a config file int dataLayer which is a class library and put the connection string there – Whiplash Oct 03 '18 at 11:20

4 Answers4

0

how can I pass the connection string from the presentation layer to the data layer most efficient way. Is there a similar way how i used to pass the connection string when i was working with .Net framework.

In Asp.Net Core, it is much easier to passing connection to DbConnection with dependence Injection.

  • Change DbConnection to accept connection string

    public class DbConnection
    {
    public DbConnection(string connectionString)
    {
        _sqlConnection = new SqlConnection(connectionString);
    }
    
  • Register DbConnection in PresentationLayer

    services.AddTransient<DbConnection>(serviceProvider => new DbConnection(Configuration.GetConnectionString("DefaultConnection")));
    
Edward
  • 28,296
  • 11
  • 76
  • 121
  • The DbConnection class it is in the dataLayer which is a class library. the presenation layer don't now about the dataLayer – Whiplash Oct 03 '18 at 11:18
  • @Whiplash References in .Net Core are transitive meaning that if `ProjectA` has a reference to `ProjectB` and `ProjectB` references `ProjectC`, then `ProjectA` will be able to see everything in `ProjectC`. – DavidG Oct 03 '18 at 11:34
0

Create AppSettings class

public static class AppSettings
{
    public static string ConnectionString { get; set; }
}

In Startup.cs

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
    BuildAppSettingsProvider();
}

public IConfiguration Configuration { get; }

private void BuildAppSettingsProvider()
{
    AppSettings.ConnectionString = Configuration["ConnectionString"];
}

now you can access AppSettings in your presentation layer.

100% works.

Prabhu Manoharan
  • 311
  • 2
  • 10
0

When you have multiple layers you most likely have an IOC Container in use. Create an interface in your datalayer and do the implementation in your view layer and then register and get it with your IOC Container. This is the most clean way to do it if you cant pass it directly in your SqlConnection.

BrunoVT
  • 723
  • 6
  • 22
0

There are (min) 3 options. I think the best one is to use an IoC container. Maybe you prefer to add an appconfig file to DB layer and access to it for layer specific settings. Or, you can use the default injection mechanism to pass the IConfiguration to Business Layer, and then pass it to DataLayer via ctors.

For example

/* ----- Startup.cs ----- */
public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IxxxService, xxxBusinessService>();
}

/* ----- UI Layer ----- */
public xxxController(IxxxService xxxBusinessService)
{
   this.xxxBusinessService = xxxBusinessService;
}

/* ----- BUSINESS LAYER ----- */
/*
UI/controller knows Business service and IConfiguration objects, and default 
injector automatically creates/passes configuration object via ctor to Business layer.
*/
public xxxService(IConfiguration configuration)
{
    this.xxxRepository = new xxxRepository(configuration);
}

/* ----- DATA LAYER ----- */
public class xxxRepository: BaseRepository, IxxxRepository
{
    public xxxRepository(IConfiguration configuration)
        : base(configuration)
    {

    }
}       

public class BaseRepository{

    protected xxxDbContext context;

    public BaseRepository(IConfiguration configuration)
    {   
        var optionsBuilder = new DbContextOptionsBuilder<xxxDbContext>();

        optionsBuilder.UseSqlServer(configuration.GetSection("ConnectionString")["DefaultConnection"]);

        this.context = new xxxDbContext(optionsBuilder.Options);
    }
}
mutlugokhan
  • 91
  • 2
  • 4