Generic repository issue with inheritance - c#

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();
}
}

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()
{
// ...
}

Confession: I have no knowledge of PetaPoco and its template generator.
The problem is more related to OO (specifically Inheritance) than PetaPoco IMHO. If generic repository is created with Record<T> which is also a base class for each entity, then what happening is as expected. You need to closely look into inheritance of your classes.
You may need to make few changes in the solution I am proposing below to match up with ORM functionality.
Solution 1:
Declare a new base class or interface something like below:
public interface IEntityBase{.....
Include the necessary members like Delete method in interface.
Then, derive each entity from this interface as well:
public partial class Document : Record<Document>, IEntityBase
Then, create a generic repository with this interface instead of Record<T> something like below:
public abstract class GenericRepository<T> : IGenericRepository<T> where T : IEntityBase
This way, you achieve your objective without changing much of your existing code.
Solution 2:
Another dirty solution is to cast the Record<T> to its actual instance.
public void Delete(T entity)
{
if(typeof(T) == typeof(Document))
Document myEntity = (Document)entity;
myEntity.Delete();
}
Casting in each method is definitely bad idea. Look for some better centralized location in your code. I just wanted to show you the way.
Solution 3:
Other thought is to make Delete method in Record<T> a virtual method. But I am not sure how your ORM works or even if your ORM allows this, so I will not comment on this.

Related

C# Abstract Method to enforce update method

In our code base we have a base model (PersistenceEntity) that handles any models that are persisted to storage via a generic repository. This works well for fetching, adding and deleting. The area I want to improve is our update method to be encapsulated in the repository rather than fetching the object in the service layer, manipulating it (in whatever fashion the developer sees fit) and then saving it.
The repository update method should internally load the model, call the update method on the object and then save it (or call the AddOrUpdate extension).
To do this, I was thinking I could add an abstract method on the base class to enforce the developer to implement the update in the model rather than setting the properties in another layer.
public abstract T Update<T>(T existing) where T : PersistenceEntity;
So this would make the developer write a model that would like this:
public class MyClass : PersistenceEntity
{
public override MyClass Update<MyClass>(MyClass existing)
{
existing.SomeProperty = SomeProperty;
existing.SomeProperty2 = SomeProperty2;
return existing;
}
}
But when I implement it in this way, the compiler complains as the it thinks MyClass is the name of T and not the concrete class. I think I'm missing something obvious here, but I just can't see it... Any suggestions would be appreciated.
You can avoid hiding a class by type parameter by making a PersistenceEntity class generic itself
public abstract class PersistenceEntity<T> where T : PersistenceEntity<T>
{
public abstract T Update(T existing);
}
It means self-referencing generic constraint, because every class inheriting PersistenceEntity should update an existing instance of itself type.
The implementation for MyClass would be the following:
public class MyClass : PersistenceEntity<MyClass>
{
public override MyClass Update(MyClass existing)
{
existing.SomeProperty = SomeProperty;
existing.SomeProperty2 = SomeProperty2;
return existing;
}
}
Another option is to create an invariant interface, which incapsulates the Update method (if you aren't allowed to make PersistenceEntity class generic)
public interface IUpdate<T> where T : PersistenceEntity
{
T Update(T existing);
}
And then implement it
public class MyClass : PersistenceEntity, IUpdate<MyClass>
{
public MyClass Update(MyClass existing)
{
existing.SomeProperty = SomeProperty;
existing.SomeProperty2 = SomeProperty2;
return existing;
}
}

In EF6, how to create a generic method to get entities using a common field/column

im sorry if the title isnt enlightening enough after a while i couldnt come with a phrase to explain my problem.
Its like this:
I'm using EF6, Database first approach. All my entities have an ID and an Enabled property.
I have the EDMX file on my DAL and now i need to design the Business Layer (BLL for me).
Since i will need to validate what data comes from the DAL and is visible to the rest of the app i decided to create an interface for the common operators, create a base class that implements that and have all my custom database-tables\entities providers inherit that.
If that doesnt make sense, here is what i'm doing: (All of this is in BLL)
public interface IEntityManager<T> where T : class {
void Add(T e, bool commit=false);
void Delete(T e);
void DeleteByID(int id);
void Update(T e);
IQueryable<T> Search(Expression<Func<T, bool>> predicate);
IQueryable<T> GetAll();
T Get(int id);
}
Now, the base class that implements the common operations is this: (edited for readability and brevity)
public class EntityManager<TEntity> : IDisposable, IEntityManager<TEntity> where TEntity : class {
private readonly DbContext _ctx;
private readonly DbSet<TEntity> _set;
public EntityManager() {
_ctx = new DomainModelFactory();
_set = _ctx.Set<TEntity>();
}
public void Add(TEntity e) {
_set.AddOrUpdate(e);
}
//other methods here
public TEntity Get(int id) {
return _set.Find(id);
}
}
To create managers that will actually access the data and make it usable across the application, i'm planning on doing something like:
public class VenueManager: EntityManager<Venue> {
public VenueManager():base() {
}
}
For the class that will manage my Venue entity. I am creating classes instead of using something like
var venueManager = new EntityManager<Venue>();
because these classes will have some specialized methods.
I hope you could understand what i have done so far (and it works)
Now, my problem is that every entity has two common fields: ID (int) and Enabled (bool)
I am to use these when deleting by id and when coding Get and GetAll because i must only
get items that have Enabled=true. Now, i know that since i'm create Manager classes i could just use c&p the code, but i was wondering, is there a way that i can code this in the EntityManager class and have all the managers inherit the method but using the concrete classes ?
something like this:
In EntityManager class:
public TEntity Get(int id) {
return _set.Where(T.ID==id);
}
Thats basically what i want: a way to use these properties at the base class (EntityManager) where they matter (methods deletebyid, get and getall) in a way that all Manager classes (ManagerVenue in the example) inherit these methods so that i wont have to write them all over and over? (got some 100 entities)
You should define a base class or interface for all your entities, something like:
public class Entity {
public int Id { get; set; }
public bool Enabled { get; set; }
}
And in your EntityManager class add a generic constraint to TEntity like where TEntity : Entity
Then you will be able to use the common properties Id and Enabled inside your base class EntityManager.

Using Generics in C# - Calling Generic class from a Generic class

I have a class similar to the following:
public abstract class Manager<T, TInterface> : IManager<T> where TInterface : IRepository<T>
{
protected abstract TInterface Repository { get; }
public virtual List<T> GetAll()
{
return Repository.GetAll();
}
}
This works perfectly fine, however, is there a way to get away from having the TInterface in the abstract class declaration and in the resulting class that extends my generic abstract class:
public class TestManager : Manager<TestObject, ITestRepository>, ITestManager
I am forced to use ITestRepository and make the Repository property abstract due to the fact that it can contain custom methods that I need to know about and be able to call.
As I continue to build layers, I will have to keep doing this process the whole way up the stack. Examples would be if I had a generic abstract controller or service layer:
public class TestService : Service<TestObject, ITestManager>, ITestService
Is there a better way to do this or is this the best practice to allow a generic class to call another generic class?
It seems that all you want to do is to make Manager<T> testable, and use a mock as a repository that you can query for special members.
If that's the case, maybe you can change your design to this:
public class Manager<T> : IManager<T> {
protected IRepository<T> Repository { get; set; }
// ...
public virtual List<T> GetAll() {
return Repository.GetAll();
}
}
Now, all the specifics of testing are in a testing subclass:
public class TestingManager<T> : Manager<T> {
public new ITestRepository<T> Repository {
get {
return (ITestRepository<T>)base.Repository;
}
set {
base.Repository = value;
}
}
}
When you write your unit tests, you create TestingManager<T> instances (referenced through TestingManager<T> declared variables and fields), and you provide them with a test repository. Whenever you query their Repository, you'll always get a strongly-typed test repository.
UPDATE:
There's another way to solve this, without a subclass. You declare your repository objects as test repositories that you pass to Manager<T>s and you query them directly, without going through the Manager<T>.
[Test]
public void GetAll_Should_Call_GetAll_On_Repository_Test() {
var testRepository = new TestRepository();
var orderManager = new Manager<Order>(testRepository);
// test an orderManager method
orderManager.GetAll();
// use testRepository to verify (sense) that the orderManager method worked
Assert.IsTrue(testRepository.GetAllCalled);
}
No, you can't get around it. You can try, but the result will be ugly and in some way incorrect. The reason is that you are asking generics not to be generic but still be generic.
If a new class uses a generic class, either in inheritance or composition, and it itself does not know enough to specify the type parameters to the generic class it is using, then it must itself be generic. It is analogous the method call chains, where a method may pass parameters along to another method. It can't make up the arguments to the inner method, but must rather take them as parameters itself from a caller that does know what they are. Type parameters are the same.
One thing that does make this feel like code smell is the fact that you can't have a variable of type Manager<,>. It has to be fully type-specified. One solution I've come up with is to have non-generic interfaces that the generic classes implement. These interfaces have as much of the public interface of the generic class as is possible (they can't have methods or properties that reference the type parameters). Then you can pass around variables of the type of the interface and not have to specify type parameters.
Example:
interface IExample {
string Name { get; }
void SomeNonGenericMethod(int i);
}
class Example<T> : IExample {
public string Name { get { ... } }
public void SomeNonGenericMethod(int i) {
...
}
public T SomeGenericMethod() {
...
}
}

Redefine method return type in derived class without generics

TL;DR:
Is there some way to add an abstract method to a base class that allows derived classes to override the method's return type, without the use of generics, and without the use of the new keyword?
I'm working on developing some custom templates for LLBLGen Pro. In the process, I refuse to change the default templates that LLBLGen Pro offers, so that my approach doesn't overwrite other peoples' files if they choose to implement my templates.
One task I've started working on (and made good headway toward) is developing a template that generates a DTO for each entity. Along those lines, one objective is to provide my entities with a ToDTO() method. In the interest of generic programming, I've decided to define this method within a common base class, and this is where my trouble starts.
Keep in mind that the purpose of defining the ToDTO() method in the base class is because I'm looking to create a generic repository (with a Fetch() method, for example) that I'd like to have work off the CommonEntityBase, as opposed to a specific entity.
LLBLGen defines its CommonEntityBase class like so:
public abstract partial class CommonEntityBase : EntityBase2 {
// LLBLGen-generated code
}
My original plan was to add my method to another partial class like so:
public abstract partial class CommonEntityBase {
public abstract CommonDTOBase ToDto();
}
I thought that the inherited classes would be able to define the return type in their methods as a type derived from the base class's return type, like so:
public partial class PersonEntity : CommonEntityBase {
public override PersonDTO ToDto(){ return new PersonDTO(); }
}
but I was wrong.
My second attempt was to define the class using generics, as such:
public abstract partial class CommonEntityBase<T> : CommonEntityBase
where T : CommonDTOBase {
public abstract T ToDto();
}
Simple enough. All I'd have to do is have my generated entity classes inherit from this new entity base. Just one caveat. As I don't want to overwrite LLBLGen's templates, it's back to partial classes.
LLBLGen's individual entities have this definition:
public partial class PersonEntity : CommonEntityBase {
// LLBLGen-generated code
}
And herein lies my problem. In order for my method to work, I would have to create my own partial class with this definition:
public partial class PersonEntity : CommonEntityBase<PersonDTO> {
public override PersonDTO ToDto(){ return new PersonDTO(); }
}
Of course, this isn't possible, because, as I now know,
All of the parts [of a partial class] that specify a base class must agree, but parts that omit a base class still inherit the base type.
The third thing I was going to attempt was simply overriding the base class's function definition with the new keyword:
public abstract partial class CommonEntityBase {
public virtual CommonDTOBase ToDto(){ return null; }
}
public partial class PersonEntity : CommonEntityBase {
public new PersonDTO ToDto(){ return new PersonDTO(); }
}
However, this defeats the purpose of my approach completely, as I want to be able to access PersonEntity's ToDTO() method when it's cast as a CommonEntityBase. With this approach, doing:
CommonEntityBase e = new PersonEntity();
var dto = e.ToDto();
would result in dto being null, which I don't want.
I've come across various links discussing my first approach, and why it won't work, and typically pointing to my generic approach as a solution in the general sense. However, in my situation, generics do not appear to work.
All this to ask whether or not what I'm trying to accomplish is possible.
Is there some way to add an abstract method to a base class that allows derived classes to override the method's return type, without the use of generics, and without the use of the new keyword?
Or perhaps I'm approaching this from the wrong angle, and there's some other technique that could solve my problems?
EDIT
Here's a use-case for what I'd like to accomplish with the entities, taking Porges's approach:
public class BaseRepository<D,E> where D : CommonDTOBase where E : CommonEntityBase,new
public D Get(Guid id){
var entity = new E();
entity.SetId(id);
// LLBLGen adapter method; populates the entity with results from the database
FetchEntity(entity);
// Fails, as entity.ToDto() returns CommonDTOBase, not derived type D
return entity.ToDto();
}
}
Instead of:
public abstract partial class CommonEntityBase {
public abstract CommonDTOBase ToDto();
}
public partial class PersonEntity : CommonEntityBase {
public override PersonDTO ToDto(){ return new PersonDTO(); }
}
Why are you not just returning a DTO like this:
public abstract partial class CommonEntityBase {
public abstract CommonDTOBase ToDto();
}
public partial class PersonEntity : CommonEntityBase {
// changed PersonDTO to CommonDTOBase
public override CommonDTOBase ToDto(){ return new PersonDTO(); }
}
I think that's more idiomatic for OO code. Is there a reason you need to know the exact type of the DTO?
I don't know LLBLGen, but I believe you could solve your problem this way, by introducing an interface to hold the type parameter:
public interface DTOProvider<T> where T : CommonDTOBase {
public T ToDTO();
}
And then for your entity classes, do this:
public partial class PersonEntity : CommonEntityBase, DTOProvider<PersonDTO> {
public PersonDTO ToDto() { return new PersonDTO(); }
}
Because partial classes can introduce different interfaces, this works. The only sadness is that a cast is required to get access to the method via the base type:
public void DoSomethingWithDTO<T>(CommonBaseEntity entity)
where T : CommonDTOBase {
T dto = ((DTOProvider<T>) entity).ToDTO();
...
}
Of course, you can call ToDTO directly without the cast when you have a reference of one of the entity derived types:
public void DoSomethingWithPersonDTO(PersonEntity entity)
{
PersonDTO dto = entity.ToDTO();
...
}
If you are using .NET Framework 4, you can use generic variance to make the DTOProvider interface easier to use from code that just cares about working with CommonDTOBase by declaring the DTO type covariant:
public interface DTOProvider<out T> where T : CommonDTOBase {
public T ToDTO();
}
(Notice the 'out'.) Then your DoSomethingWithDTO method doesn't need the type parameter:
public void DoSomethingWithDTO(CommonBaseEntity entity) {
CommonDTOBase dto = ((DTOProvider<CommonDTOBase>) entity).ToDTO();
...
}
It is tempting to try and declare : CommonBaseEntity, DTOProvider<T> on the CommonBaseEntity partial class. Unfortunately that doesn't work, because when the partial definitions are merged the type parameter is carried over and your CommonBaseEntity type ends up being a generic type, which it looks like is what got you into a bind in the first place.

Trouble with abstract generic methods

Let's say I have a class library that defines a couple entity interfaces:
public interface ISomeEntity { /* ... */ }
public interface ISomeOtherEntity { /* ... */ }
This library also defines an IRepository interface:
public interface IRepository<TEntity> { /* ... */ }
And finally, the library has an abstract class called RepositorySourceBase (see below), which the main project needs to implement. The goal of this class is to allow the base class to grab new Repository objects at runtime. Because certain repositories are needed (in this example a repository for ISomeEntity and ISomeOtherEntity), I'm trying to write generic overloads of the GetNew<TEntity>() method.
The following implementation doesn't compile (the second GetNew() method gets flagged as "already defined" even though the where clause is different), but it gets at what I'm trying to accomplish:
public abstract class RepositorySourceBase // This doesn't work!
{
public abstract Repository<TEntity> GetNew<TEntity>()
where TEntity : SomeEntity;
public abstract Repository<TEntity> GetNew<TEntity>()
where TEntity : SomeOtherEntity;
}
The intended usage of this class would be something like this:
public class RepositorySourceTester
{
public RepositorySourceTester(RepositorySourceBase repositorySource)
{
var someRepository = repositorySource.GetNew<ISomeEntity>();
var someOtherRepository = repositorySource.GetNew<ISomeOtherEntity>();
}
}
Meanwhile, over in my main project (which references the library project), I have implementations of ISomeEntity and ISomeOtherEntity:
public class SomeEntity : ISomeEntity { /* ... */ }
public class SomeOtherEntity : ISomeOtherEntity { /* ... */ }
The main project also has an implementation for IRepository<TEntity>:
public class Repository<TEntity> : IRepository<TEntity>
{
public Repository(string message) { }
}
And most importantly, it has an implementation of the abstract RepositorySourceBase:
public class RepositorySource : RepositorySourceBase
{
public override IRepository<ISomeEntity> GetNew()
{
return new (IRepository<ISomeEntity>)Repository<SomeEntity>(
"stuff only I know");
}
public override IRepository<ISomeOtherEntity> GetNew()
{
return new (IRepository<ISomeEntity>)Repository<SomeOtherEntity>(
"other stuff only I know");
}
}
Just as with RepositorySourceBase, the second GetNew() method gets flagged as "already defined".
So, C# basically thinks I'm repeating the same method because there's no way to distinguish the methods from their parameters alone, but if you look at my usage example, it seems like I should be able to distinguish which GetNew() I want from the generic type parameter, e.g, <ISomeEntity> or <ISomeOtherEntity>).
What do I need to do to get this to work?
Update
I ended up solving this using specifically-named methods and a Func<T, TResult> parameter.
So, RepositorySourceBase now looks like this:
public abstract class RepositorySourceBase
{
public abstract Repository<ISomeEntity> GetNewSomeEntity();
public abstract Repository<ISomeOtherEntity> GetNewSomeOtherEntity();
}
And RepositorySource looks like this:
public class RepositorySource : RepositorySourceBase
{
public override IRepository<ISomeEntity> GetNewSomeEntity()
{
return new (IRepository<ISomeEntity>)Repository<SomeEntity>(
"stuff only I know");
}
public override IRepository<ISomeOtherEntity> GetNewSomeOtherEntity()
{
return new (IRepository<ISomeEntity>)Repository<SomeOtherEntity>(
"other stuff only I know");
}
}
Now, what started this whole thing off was that I needed a generic RepositoryUtilizer class that could grab a repository from a source simply by knowing the type of repository (which could be specified as a generic type parameter). Turns out, that wasn't possible (or at least not easily possible). However, what is possible is to use the Func<T, TResult> delegate as a parameter to allow the RepositoryUtilizer class to obtain the repository without needing to "know" the method name.
Here's an example:
public class RepositoryUtilizer
{
public DoSomethingWithRepository<TEntity>(
Func<TRepositorySource, IRepository<TEntity>> repositoryGetter)
{
using (var repository = repositoryGetter(RepositorySource))
{
return repository.DoSomething();
}
}
}
}
You cannot get this work as you intended. Type constraints cannot be used to decide between your two methods.
public abstract Repository<TEntity> GetNew<TEntity>()
where TEntity : SomeEntity;
public abstract Repository<TEntity> GetNew<TEntity>()
where TEntity : SomeOtherEntity;
Assume
public class SomeEntity { }
public class SomeOtherEntity : SomeEntity { }
and SomeOtherEntity is a valid type argument for both methods yielding two methods with identical signature.
The way to go is probably a single generic method that uses the supplied type argument to dispatch the call to the desired implementation. This is in turn probably solved most easily by implementing an interface on all concrete types.
Constraints are not part of the signature. This fact has numerous ramifications, many of which apparently irk people to no end. For some of those ramifications, and about a million comments telling me that I am WRONG WRONG WRONG, see this article and its accompanying comments.
http://blogs.msdn.com/ericlippert/archive/2009/12/10/constraints-are-not-part-of-the-signature.aspx
I would solve your problem by having two methods with two different names.
The only solution I can think of is to define an IRepositorySource<T> interface that each RepositorySource class can implement explicitly:
public interface IRepositorySource<T>
{
IRepository<T> GetNew();
}
public class RepositorySource : IRepositorySource<ISomeEntity>, IRepositorySource<ISomeOtherEntity>
{
IRepository<ISomeEntity> IRepositorySource<ISomeEntity>.GetNew()
{
...
}
IRepository<ISomeOtherEntity> IRepositorySource<ISomeOtherEntity>.GetNew()
{
...
}
}
To access these methods you'll need to cast a RepositorySource instance into the required interface type e.g.
IRepository<IEntity> r = ((IRepositorySource<IEntity>)repositorySource).GetNew();
public class RepositorySource
{
static IRepository<T> IRepositorySource.GetNew<T>()
{
if (typeof(T) == typeof(ISomeEntity))
return (IRepository<T>)new SomeEntityRepository();
...
}
}

Categories