Generic Repository & Dependency Injection with .NET Core 23


With the release of .NET Core in late June, everything is new again! It’s incredibly exciting to be a developer in the .NET stack. Kudos to Microsoft and the .NET team for a job well done.

With all of the frenzy I thought I might put together a little sample project. This will be an example of how to get started using a Generic Repository, the built-in Dependency Injection framework, Entity Framework Core, and the new .NET Core.

 

Generic Repository

I’ve been using a Generic Repository in some form or fashion for the last few years. I find it best to abstract away the details of the data access layer from the rest of the application. By using a Generic Repository, it’s much easier to keep from business logic creeping in where it doesn’t belong.

My preference is to keep the Repository as simple and clean as possible. No more than simple CRUD (Create, Read, Update, and Delete) routines should exist here. You may notice that I’ve omitted the Delete in this case. I find it best never to delete anything, choosing instead to mark a record inactive with a simple update.

Let’s start with a simple Interface:

    public interface IRepository<T>
    {
        T Get<TKey>(TKey id);
        IQueryable<T> GetAll();
        void Add(T entity);
        void Update(T entity);
    }

And the implementation:

    public class Repository<T> : IRepository<T> where T : class
    {
        protected readonly DbContext Context;
        protected DbSet<T> DbSet;

        public Repository(ExampleContext context)
        {
            Context = context;
            DbSet = context.Set<T>();
        }

        public void Add(T entity)
        {
            Context.Set<T>().Add(entity);

            Save();
        }

        public T Get<TKey>(TKey id)
        {
            return DbSet.Find(id);
        }

        public IQueryable<T> GetAll()
        {
            return DbSet;
        }

        public void Update(T entity)
        {
            Save();
        }

        private void Save()
        {
            Context.SaveChanges();
        }
    }

By using the Generic Repository you can eliminate having numerous explicit repository classes strewn throughout your application. Where you might normally have 1 repository class per database object, now this can be handled by a single Generic Repository.

Of course the Generic Repository pairs up nicely with Entity Framework, my current ORM of choice. There are a few caveats with the first release of EF Core, however.

 

Entity Framework Core

dbfindThanks to Julie Lerman and the Entity Framework team for replying to my tweet regarding DbSet.Find. Find has not yet been implemented, but there are plenty of examples of extension methods to implement this. You’ll notice that I’ve included Find in my Generic Repository, so you’ll either have to implement an extension method, use a nightly build, or wait for the 1.1 release of EF Core.

Julie was kind enough to follow up with a blog post about the roadmap, and a few days later the EF team posted Entity Framework Core 1.1 Plans. More exciting enhancements, improvements, and implementations of missing features to come.

Another potential issue to be aware of, lazy loading has not yet been implemented. While not terribly alarming, if you’ve depended on this in the past, you’ll need to take this into account by using the Include extension or explicit joins within your queries.

As an exercise I would ask you to implement Find on your own.

 

Dependency Injection

It seems the .NET Framework finally has a first-class Dependency Injection Framework. I’ve used a variety of 3rd party Dependency Injection Containers in the past. I’m happy to see the setup and usage of the new DI Framework is as simple and straight forward as many of the other popular players.

Just a few lines to get you started injecting a Generic Repository and a Service from our Business Layer:

            services.AddScoped(typeof(IRepository<>), typeof(Repository<>));

            services.AddTransient<IHorseService, HorseService>();

Here you can see that we’re injecting the Generic Repository with an empty type argument. Normally we would have to define a specific typed repository (ie: services.AddScoped(IRepository<User>, Repository<User>)). By defining the signature with typeof(IRepository<>) argument we’re able to tell our DI framework to declare and inject the proper concrete class at run-time.

And of course, don’t forget to include your DbContext, which will be used by our Repository:

            services.AddDbContext<ExampleContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

 

Example Project

I’ve put together a complete solution to play with and made it available on GitHub. Feel free to download, play around, and submit pull requests.

###

Any updates will be listed below:

  • 8/04/2016 – Initial post

 


Please Consider Sharing This Post:

FacebooktwitterredditlinkedinFacebooktwitterredditlinkedin