0

Ok, I might be punching above my pay grade here, but I'm trying to create a generic CRUD routine for and EF project. I've got most of it working but I'm flailing around on one point.

Normally you do something like this to add an entity through a context-

DBContext.MyClass.Add( p ); // p = instance of MyClass

That works fine, but since in a global method to handle all adds regardless of what class they are I'm passing in a Model as an object it would look more like this-

DBContext<whateverobject>.Add(whateverobject); // my objects is an object param passed into the method

I've tried doing a bunch of typeofs and there where T : class stuff but I'm having no luck. Any pointing in the right direction would help me out.

I'm using EF Core 2 so my options might also be more limited than EF 6.

Thanks.

Erik Philips
  • 53,428
  • 11
  • 128
  • 150
infocyde
  • 4,140
  • 2
  • 25
  • 36
  • 1
    Does this make sense: https://stackoverflow.com/questions/30675564/in-entity-framework-how-do-i-add-a-generic-entity-to-its-corresponding-dbset-wi – Erik Philips Nov 07 '17 at 23:53
  • Erik, I think that will put me on the right track, if you put it as an answer I'll give you credit for it. – infocyde Nov 08 '17 at 00:04
  • 1
    Test it first, then I'll answer it :) I don't want other people find this then not being able to use it because it wrong. – Erik Philips Nov 08 '17 at 00:05
  • Just to mention that in EFC it's even easier - you could do simply `dbContext.Add(entity)` – Ivan Stoev Nov 08 '17 at 09:13
  • Tested Eric, at least to the point where I'm leaving it, turns out I won't be using a generic CRUD method after all for a variety of reasons, but it was a good learning experience. Post an answer by the end of today and I'll give it you. Thanks. – infocyde Nov 08 '17 at 17:34

1 Answers1

4

The method you're looking for is DbContext's Set<T>()

Your generic repository for your generic CRUD would look something like this:

public class Repo<T> where T: class
{
    private readonly DbSet<T> _set; 

    public Repo(DbContext dbContext)
    {
        _set = dbContext.Set<T>();
    }

    public void Add(T entity) => _set.Add(entity);
}

This example includes a maybe unusual thing:

where T: class: we have to specify that T has to be a reference type because DbSet<T> expects T to be a reference type


For generic querying you might want to use extension methods. In order to implement a ById method you'd have to specify that the type T must have an Id property using an interface. That would look something like this:

public interface IEntity
{
    int Id { get; set; }
}

public class User : IEntity
{
    public int Id { get; set; }
}

public static class DbSetExtensions
{
    public static T ById<T>(this DbSet<T> dbSet, int id) where T: class => 
        dbSet.FirstOrDefault(entity => entity.Id == id);
}
Maximo Dominguez
  • 2,075
  • 18
  • 35
  • This is a great answer but I already promised I'd give the answer to Erik Philips who pointed me in the right direction yesterday. But for people looking for the way to go this is also a good starting point. – infocyde Nov 08 '17 at 17:35
  • Thanks for the compliment. I only hope you can solve your problem – Maximo Dominguez Nov 08 '17 at 17:37