This example injects the `IRepository<IdentityUser, Guid>` (default repository) which defines the standard repository methods and implements the `IQueryable` interface.
In addition, Identity module defines the `IIdentityUserRepository` (custom repository) that can also be injected and used by your application. `IIdentityUserRepository` provides additional custom methods for the `IdentityUser` entity while it does not implement the `IQueryable`.
> In addition, Identity module defines the `IIdentityUserRepository` (custom repository) that can also be injected and used by your application. `IIdentityUserRepository` provides additional custom methods for the `IdentityUser` entity while it does not implement the `IQueryable` interface.
###### Create a New Entity
TODO
Working with an entity of a module is easy if you want to use the entity as is. However, you may want to define your own entity class and map to the same database table in the following cases;
* You want to add a new field to the table and map it to a property in the entity. You can't use the module's entity since it doesn't have the related property.
* You want to use a subset of the table fields. You don't want to access to all properties of the entity and hide the unrelated properties (from a security perspective or just by design).
* You don't want to directly depend on a module entity class.
In any case, the progress is same. Assume that you want to create an entity, named `AppRole`, mapped to the same table of the `IdentityRole` entity of the [Identity module](Modules/Identity.md).
Here, we will show the implementation, then **will discuss the limitations** (and reasons of the limitations) of this approach.
First, create a new `AppRole` class in your `.Domain` project:
````csharp
using System;
using Volo.Abp.Domain.Entities;
using Volo.Abp.MultiTenancy;
namespace Acme.BookStore.Roles
{
public class AppRole : AggregateRoot<Guid>, IMultiTenant
{
// Properties shared with the IdentityRole class
public Guid? TenantId { get; private set; }
public virtual string Name { get; protected internal set; }
//Additional properties
public string Title { get; set; }
private AppRole()
{
}
}
}
````
* It's inherited from [the `AggregateRoot<Guid>` class](Entities.md) and implements [the `IMultiTenant` interface](Multi-Tenancy.md) because the `IdentityRole` also does the same.
* You can add any properties defined by the `IdentityRole` entity. This examples add only the `TenantId` and `Name` properties since we only need them here.
* You can add custom (additional) properties. This example adds the `Title` property.
* The constructor is provide, so it is not allowed to directly create a new `AppRole` entity. Creating a role is a responsibility of the Identity module. You can query roles, set/update your custom properties, but you should not create or delete a role in your code, as a best practice (while there is nothing restricts you).
Now, it is time to define the EF Core mappings. Open the `DbContext` of your application (`BookStoreDbContext` in this sample) and add the following property:
````csharp
public DbSet<AppRole> Roles { get; set; }
````
Then configure the mapping inside the `OnModelCreating` method (after calling the `base.OnModelCreating(builder)`):
/* Configure the shared tables (with included modules) here */
//CONFIGURE THE AppRole ENTITY
builder.Entity<AppRole>(b =>
{
b.ToTable("AbpRoles");
b.ConfigureByConvention();
b.ConfigureCustomRoleProperties();
});
...
/* Configure your own tables/entities inside the ConfigureBookStore method */
builder.ConfigureBookStore();
}
````
We added the following lines:
````csharp
builder.Entity<AppRole>(b =>
{
b.ToTable("AbpRoles");
b.ConfigureByConvention();
b.ConfigureCustomRoleProperties();
});
````
* It maps to the same `AbpRoles` table shared with the `IdentityRole` entity.
* `ConfigureByConvention()` configures the standard/base properties (like `TenantId`) and recommended to always call it.
`ConfigureCustomRoleProperties()` has not exists yet. Define it inside the `BookStoreDbContextModelCreatingExtensions` class (near to your `DbContext` in the `EntityFrameworkCore` project):
````csharp
public static void ConfigureCustomRoleProperties<TRole>(this EntityTypeBuilder<TRole> b)
* This method only defines the custom properties of your entity.
* Unfortunately, we can not utilize the fully type safety here (by referencing the `AppRole` entity). The best we can do is to use the `Title` name as type safe.
You've configured the custom property for your `DbContext` used by your application on the runtime. We also need to configure the `MigrationsDbContext`. Open the `MigrationsDbContext` (`BookStoreMigrationsDbContext` for this example) and change as shown below:
/* Include modules to your migration db context */
...
/* Configure customizations for entities from the modules included */
//CONFIGURE THE CUSTOM ROLE PROPERTIES
builder.Entity<IdentityRole>(b =>
{
b.ConfigureCustomRoleProperties();
});
...
/* Configure your own tables/entities inside the ConfigureBookStore method */
builder.ConfigureBookStore();
}
````
Only added the following lines:
````csharp
builder.Entity<IdentityRole>(b =>
{
b.ConfigureCustomRoleProperties();
});
````
In this way, we re-used the extension method that is used to configure custom property mappings for the role. But, this time, did the same customization for the `IdentityRole` entity.
Now, you can add a new EF Core database migration using the standard `Add-Migration` command in the Package Manager Console (remember to select `.EntityFrameworkCore.DbMigrations` as the Default Project in the PMC):