4

I'm trying to use the knowledge I've gained from studying SOLID principles to make a simple ASP.NET Webform.

I've set up my solution into 3 projects: the main asp.net webforms project, the Data Access Interfaces class library project, and the Data Access class library project (which has the implementations for the interfaces in the Data Access Interfaces project).

I have an ICoinStorage interface in the Data Access Interfaces assembly that looks like this (Coin is just a DTO class that lives in the Data Access Interfaces assembly):

public interface ICoinStorage
{
    void Persist(IEnumerable<Coin> coins);
}

And the implementation of that interface uses ADO.NET in the Data Access assembly called CoinSqlServerStorage looks like this:

public class CoinSqlServerStorage : ICoinStorage
{
    private string sqlConnectionString;

    public CoinSqlServerStorage(string connectionStringName)
    {
        sqlConnectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;
    }

    public void Persist(IEnumerable<Coin> coins)
    {
        using (var connection = new SqlConnection(sqlConnectionString))
        using (var command = new SqlCommand() { Connection = connection })
        {
            foreach (var coin in coins)
            {
                command.Parameters.AddWithValue("@Name", coin.Name);
                command.Parameters.AddWithValue("@Weight", coin.Weight);
                command.Parameters.AddWithValue("@Thickness", coin.Thickness);
                command.Parameters.AddWithValue("@Value", coin.Value);
                command.Parameters.AddWithValue("@Condition", (int)coin.Condition);

                command.CommandText = "INSERT INTO Coins (Name, Weight, Thickness, Value, ConditionID) " +
                                      "VALUES (@Name, @Weight, @Thickness, @Value, @Condition);";

                command.Connection.Open();
                command.ExecuteNonQuery();
            }
        }
    }
}

My question is: How do I use the CoinSqlServerStorage class in the webforms project without creating a dependency on the Data Access assembly? I want to make it so the user can visit an InsertCoin.aspx page to define a new coin and have it store the new coin in the database...

My problem arose when I was ready to make an instance of the CoinSqlServerStorage class in the Page.Load event of the InsertCoin.aspx page, but realized this would create a dependency on the Data Access assembly instead of just being dependent on the Data Access Interfaces assembly...

How do I proceed?

Lews Therin
  • 3,707
  • 2
  • 27
  • 53
  • 1
    If I understand correctly, perhaps your project is structured a bit off. There's multiple ways to go about a SOLID friendly setup, but I use the following. 1) View Project 2) Domain Project (defines Models, Services, and Repository (ICoinStorage) interfaces) 3) A project for each repository based on source type (such as SQL Server). Your view then references both the Domain project and any consumed specific repository. So in the end you'd have something like "Coin.Website", "Coin.Domain", and "Coin.Repository.SQLServer" as projects. – Ranger Apr 30 '16 at 20:07
  • 1
    That is an excellent question as most developers don't even recognize the problem let alone address it. Rather than answer it directly, I'll say 1) read about dependency injection. It's a technique/tool that makes SOLID easier to implement. 2) Look into MVC. Many aspects of good programming are harder (bordering in impossible) to implement with webforms. Dependency injection is so significant that it's built into the upcoming version of ASP.NET/MVC and webforms are going away. – Scott Hannen May 01 '16 at 00:25
  • Thanks @ScottHannen. I'm planning on learning MVC after SOLID and WCF as that is what my current job wants me to learn. For now, I need to do it in webforms. DI is a section in the SOLID book I'm currently reading, so I look forward to that. – Lews Therin May 01 '16 at 01:00
  • 2
    Related: https://stackoverflow.com/questions/9501604/ioc-di-why-do-i-have-to-reference-all-layers-assemblies-in-entry-application – Steven May 01 '16 at 12:59

3 Answers3

3

In that case you can create one more project and call that like Data Access DI which will have a references to Data Access and Data Access Interfaces projects. This project will have a responsibility to provider the required realization of Data Access Interfaces to all other project (that will require that).

But even in this case you will have a two dependencies: Data Access Interfaces and Data Access DI - first one will provide interfaces and the second one - will provide the realizations.

This Data Access DI project will isolate your other projects from the realizations even when you will have more that one Data Access Whatever projects, say: Data Access Mongo, Data Access Sql, Data Access Raven etc.

MaKCbIMKo
  • 2,800
  • 1
  • 19
  • 27
2

How do I use the CoinSqlServerStorage class in the web forms project without creating a dependency on the Data Access assembly?

Well, you could use a DI container that supports XML configuration. This will allow you to bind to the data access assembly only at run-time.

Having said that, this is not a good thing to do in most cases.

I will go back a little bit and say that it is OK for the web forms project to reference the data access library.

The web forms project is a special project, it is not just a class library. The web forms projects constitutes the application it self, and the application needs to reference all other class libraries that it uses, not just libraries that contain the interfaces.

Basically, the web forms project must contain the Composition Root, and the Composition Root needs to know everything.

You might want to take a look at this answer (and the question) for a related discussion.

Community
  • 1
  • 1
Yacoub Massad
  • 27,509
  • 2
  • 36
  • 62
0

How do I use the CoinSqlServerStorage class in the webforms project without creating a dependency on the Data Access assembly?

Why do you think that it's a problem? If you seriously do, take a look in your bin folder once the solution have been compiled. There are a lot of dependencies for your executable.

SOLID have nothing to do with assembly references. Well. Dependency Inversion Principle might.

DIP says:

A. High-level modules should not depend on low-level modules. Both should depend on abstractions.
B. Abstractions should not depend on details. Details should depend on abstractions.

In your case the the high level module (web forms project) references the low level module (DAL). And your lower layer module depends on abstractions (your dal interfaces project).

That's perfectly fine.

However, I typically add the DAL interfaces to my business layer project, as it's the needs in the BL that drives the design of the DAL interfaces.

jgauffin
  • 99,844
  • 45
  • 235
  • 372