user3748973
user3748973

Reputation: 459

ASP MVC Add ApplicationUser to Generic Repository

A few days ago I decide to use Unit of work & Generic repository In my project. After a little search I found this solution to do this.

In this pattern we have 4 layer:

1. UI
2. Model
3. Repository
4. Service

The point is all domain models inheritance from Entity class in model layer. For example :

public class Project : Entity<int> {
 ...
}

And this is my Entity class:

public abstract class BaseEntity { }
public abstract class Entity<T> : BaseEntity, IEntity<T>
{
    public virtual T Id { get; set; }
}

Now when I want to Add ApplicationUser class to UoF pattern I get an error with this concept that ApplicationUser is not inheritance from BaseEntity.

Tip : ApplicationUser is inheritance from IdentityUser class

Whats the best practice to add ApplicationUser to my design pattern?

UPDATE

I get the error message in IApplicationUserService interface

public interface IApplicationUserService : IEntityService<ApplicationUser>
{
    Task<Part> GetById(int? id);
}

IEntityService :

public interface IEntityService<T> : IService
where T : BaseEntity
{
    void Create(T entity);
    void Delete(T entity);
    Task<List<T>> GetAllAsync();
    IEnumerable<T> GetAll();
    Task Update(T entity);
}

Upvotes: 1

Views: 595

Answers (2)

Markus
Markus

Reputation: 22481

The IEntityService<T> interface has a constraint so that each type that is provided as T needs to be derived from BaseEntity. As your ApplicationUser class is derived from IdentityUser, it cannot fulfill the constraint.

You can solve this in two ways:

  1. Create a class for your users that is a real entity and therefore is derived from BaseEntity or Entity<T>. This way, the contraint is not violated. The class could be named ApplicationUserEntity or something like that. If you need to store an application user, you need to map the properties of the ApplicationUser to the ApplicationUserEntity. You might also think about whether you really need the ApplicationUser class to be derived from IdentityUser and derive it from BaseEntity instead of creating a new class.
  2. As an alternative, you can create an interface that every entity needs to implement. If your sample does show the complete BaseEntity class it does not have any members. So you can easily substitute BaseEntity by an interface, e.g. IEntity. You use this interface wherever BaseEntity is currently used, especially in the constraint. As a class can only be derived from one base class, but can implement several interfaces, you can implement IEntity in ApplicationUser so that you can use it as a type parameter for IEntityService<T>.

I'd favor the first approach as it avoids mixing authentication circumstances with persistence.

However, if you want to implement the second approach, first rename BaseEntityto IEntity, e.g. by accessing the context menu. This makes sure that the new name is used wherever BaseEntity was used before. Then change

public abstract class IEntity { }

to

public interface IEntity { }

Upvotes: 3

trailmax
trailmax

Reputation: 35106

Solution to your question is not to try to push a square peg into a round hole. Answer this question for yourself: what good the generic repository will give you when applied to Identity part of your project?

I suspect there will be a lot of pain and swearing and a ton of custom code because ApplicationUserManager probably won't work with your solution and you'll have to write a custom storage or at least partly implement some of the logic.

Just because there is a pattern, does not mean you have to apply it everywhere. Especially places where the pattern does not fit.

Upvotes: 0

Related Questions