Search code examples
c#genericsinheritancerepository-patternpetapoco

Generic repository issue with inheritance


I have N-Layer solution in .Net with PetaPoco as microORM. I get the entities generated from the template generator of PetaPoco. These entities T derive from the base class Record<T>. Then I extend them adding more data access facilities and custom Save() and Delete() methods that override the Record<T> default methods.

Following is the overrided Delete method from the entity (the method I want to call)

public partial class Document : Record<Document>
{
    public new int Delete()
    {
        int rowsAffected;
        using (var uow = DB.GetInstance().GetTransaction())
        {
            rowsAffected = base.Delete();
            LogSystem("Deleting", "Deleting a document", 0, 0, GUID);
            uow.Complete();
        }
        return rowsAffected;
    }
}

Then when I create the generic repository the methods getting called are from the base class Record<T> and not my custom ones from the entities. When I call an entityRepository.Delete() method, the Delete() method from my entity should get called and not the one from the default Record<T> class.

The generic repository class is as follwos:

public abstract class GenericRepository<T> : IGenericRepository<T> where T : Record<T>, new()
{
    public void Delete(T entity)
    {
        entity.Delete();
    }
}

Solution

  • The cause of this problem is that in your GenericRepository you specify T as "something deriving from Record". So wenn calling entity.Delete(), this call will be linked to this base method, since this is only done once for all possible instances of T.

    If you have access to the Record<T> class, just make the Delete() method virtual and override it in Document.

    If not, try using something like this:

    public class ExtendedRecord<T>: Record<T>
    {
      public virtual new int Delete()
      {
        base.Delete();
      }
    }
    
    public partial class Document : ExtendedRecord<Document>
    {
      public override int Delete()
      {
        // ...
      }
    }
    
    public abstract class GenericRepository<T> : IGenericRepository<T>
      where T : ExtendedRecord<T>, new()
    {
      // ...
    }