Dishant
Dishant

Reputation: 1595

How to avoid using data access layer in presentation layer?

I have a data layer which uses Sqlite for CRUD operation, so in my Sqlite Class I have to pass path of a DB, to do that I have interface IConnectionProvider in Data Layer as below:

public interface IConnectionProvider
 {
        string DbPath { get; }
 }

SqliteDb.cs

public class SQLiteDb : DbContext, IDbContext
    {
        internal const string DefaultDatabaseName = "My.db";

        private string connectionString = null;

        public SQLiteDb(IConnectionProvider connectionProvider)
        {
            this.connectionString = connectionProvider.DbPath;
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlite(connectionString);
        }
    }

My project architecture is as below:

 Data Layer -> View Model -> Presentation Layer

I want to avoid using Data Layer directly into Presentation layer, but to pass DBPath I have to add reference of it.

Below is the implementation of IConnectionProvider in my presentation layer:

public class SqlConnectionProvider : IConnectionProvider
    {
        public string dbPath = string.Empty;
        public string DbPath
        {
            get
            {
                if (string.IsNullOrEmpty(dbPath))
                {
                    dbPath = Path.Combine(ApplicationData.Current.LocalFolder.Path, "MyDb.sqlite");
                }

                return dbPath;
            }
        }
  }

Is there any way I can avoid using DataLayer directly into Presentation Layer? I thought of creating wrapper in VM but I don't think that it would be a good Idea as will create more dependencies.

Upvotes: 1

Views: 952

Answers (1)

modmoto
modmoto

Reputation: 3280

The common way to do this is to use the Repository Pattern. Define an Interface in the ViewModel Layer and implement it in the DataLayer. Then the ViewModel does not know anything about the DataLayer. Then instantiate the Repository with the ConnectionProvider in your main class via Dependency Injection. Also the dbContext has to move to the DataLayer and you should use it in the Repository. I would recommend putting the connection string in a config file and use this in the DL. The classes should look something like this

namespace ViewModel;
interface IDatabaseRepository {
   DataObject LoadData()
}

namespace DataLayer;
class DataRepository {
   public DataRepository(DbContext context) {
      this.context = context;
   }

   public DataObject LoadData() {
      //load data from DB using dbContext
   }
}

namespace ViewModel;
class ViewModel {
   public ViewModel(IDataRepository repository) {
      this.repository = repository;
   }

   // use the repository inside this class to acces data
}

Also look up Dependency Inversion Principle as this helps with decoupling things like that.

Upvotes: 2

Related Questions