Mike Upjohn
Mike Upjohn

Reputation: 1297

How to inherit DatabaseContext as a base class across multiple injected services

I have the following setup of a code first database with migrations in .NET Framework, and looking for what feels like there should be a better way of inheriting the DatabaseContext for CRUD to the database.

I am using Autofac dependency injection, and intend on having separate classes which inherit some form of BaseDatabaseContext class, to save me injecting the DatabaseContext class every class I write.

A sample data service class:-

public class UserRepo : BaseDatabaseContext, IUserRepo {
    public User WithCredentials(string emailAddress, string password) {
        return _database.Users.Where(x => x.EmailAddress == emailAddress && x.PasswordHash == password).SingleOrDefault();
    }
}

The BaseDatabaseContext class:

public class BaseDatabaseContext {
    public readonly DatabaseContext _database;

    public BaseDatabaseContext() {
        _database = new DatabaseContext();
    }
}

The DatabaseContext class:

public class DatabaseContext : DbContext {
    public DatabaseContext() : base("MainDatabase") {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
       /// stuff here
    }

    public DbSet<User> Users { get; set; }
    // ... more DbSet's here
}

The above works, but I am extremely unkeen, on new-ing up a new DatabaseContext() every time. I feel like I could achieve this through dependency injection but can't figure it.

My overall aim is to have the BaseDatabaseContext to basically have a public variable called, for example, database that is simple ready to go, and when inherited by the UserRepo class, I can call database.Users.XXX for example.

Can anyone point out where I am going off track? Or is what I have implemented (which does work), the best way?

Upvotes: 0

Views: 416

Answers (1)

David Browne - Microsoft
David Browne - Microsoft

Reputation: 89246

I am extremely unkeen, on new-ing up a new DatabaseContext() every time. I feel like I could achieve this through dependency injection but can't figure it.

If BaseDatabaseContext has a "dependency" on DatabaseContext, then "inject" it, typically using "construcor injection", but AutoFac also supports Property Injection:

public class BaseDatabaseContext {
    public readonly DatabaseContext _database;

    public BaseDatabaseContext(DatabaseContext db) {
        _database = db;
    }
}

A simpler pattern might be to just have your DbContext implement each of the interfaces, perhaps using Explicit Interface Implementation to avoid cluttering-up the DatabaseContext API. eg

public class DatabaseContext : DbContext, IUserRepo {
    public DatabaseContext() : base("MainDatabase") {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
       /// stuff here
    }

    public DbSet<User> Users { get; set; }
    // ... more DbSet's here

    public User IUserRepo.WithCredentials(string emailAddress, string password) {
        return this.Users.Where(x => x.EmailAddress == emailAddress && x.PasswordHash == password).SingleOrDefault();
    }
}

Upvotes: 1

Related Questions