Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what is the difference between use dbset and mappers in EF7

I started to work with .net core and Entityframework 7 in Onion Architecture! i readed this tutorial and i think its best case for learning following subject. but one part of this tutorial made a big question inside my brain. like what you see at this linked page; at Data Layer we have some classes which are our model!!

public class User : BaseEntity
{
    public string UserName { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
    public virtual UserProfile UserProfile { get; set; }
}

public class UserProfile : BaseEntity
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Address { get; set; }
    public virtual User User { get; set; }
}

and some class which are mapping above models like this !!

public class UserProfileMap
{
    public UserProfileMap(EntityTypeBuilder<UserProfile> entityBuilder)
    {
        entityBuilder.HasKey(t => t.Id);
        entityBuilder.Property(t => t.FirstName).IsRequired();
        entityBuilder.Property(t => t.LastName).IsRequired();
        entityBuilder.Property(t => t.Address);
    }
}

public class UserMap
{
    public UserMap(EntityTypeBuilder<User> entityBuilder)
    {
        entityBuilder.HasKey(t => t.Id);
        entityBuilder.Property(t => t.Email).IsRequired();
        entityBuilder.Property(t => t.Password).IsRequired();
        entityBuilder.Property(t => t.Email).IsRequired();
        entityBuilder.HasOne(t => t.UserProfile).WithOne(u => u.User).HasForeignKey<UserProfile>(x => x.Id);
    }
}

and it use this mapper classes in OnModelCreating method of DbContext for creating following models as table, in database:

public class ApplicationContext : DbContext
{
    public ApplicationContext(DbContextOptions<ApplicationContext> options) : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        new UserMap(modelBuilder.Entity<User>());
        new UserProfileMap(modelBuilder.Entity<UserProfile>());
    }
}

My big question is this: we can use DbSet<> for each entities inside the db context and avoiding writing mapper and instantiating them in OnModelCreating method of dbcontext. why this tutorial didnt use dbset ?. why we have to create mappers!

like image 971
Iman Salehi Avatar asked Jan 29 '23 23:01

Iman Salehi


2 Answers

My big question is this: we can use DbSet<> for each entities inside the db context and avoiding writing mapper and instantiating them in OnModelCreating method of dbcontext. why this tutorial didnt use dbset ?. why we have to create mappers!

new UserMap(modelBuilder.Entity<User>()); basically is EF Core way of configuring and mapping Entity to DbSet using Fluent API.

DbSet<> for each entities inside the db context and using Mapper to configuring DbSet are the same.

In Entity Framework 6, we use EntityTypeConfiguration and create mapping classes like this. It is very clean compare to Data Annotation, and follows Single Responsibility Principle.

The beauty is we just need the following code to automatically configure the hundreds of Entities using reflection.

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
   ...
   var typesToRegister = Assembly.GetExecutingAssembly().GetTypes()
        .Where(type => !string.IsNullOrEmpty(type.Namespace) &&
             type.BaseType != null &&
             type.BaseType.IsGenericType &&
             type.BaseType.GetGenericTypeDefinition() == typeof (EntityTypeConfiguration<>));

   foreach (var type in typesToRegister)
   {
      dynamic configurationInstance = Activator.CreateInstance(type);
      modelBuilder.Configurations.Add(configurationInstance);
   }

   base.OnModelCreating(modelBuilder);
}

In addition, we can use Entity Framework Power Tools, and create Entities and Mapping configuration from existing database. It only takes about a couple of minutes to generate the hundreds of tables into classes. It was a big time saver for us.

Unfortunately, EntityTypeConfiguration<T> is not available in EF Core yet as of today. I think a lot of us still like to use the old approach with new EntityTypeBuilder<T> to keep the Mapping configuration outside of DbContext, although it is not as smooth what we have done in EF6.

like image 95
Win Avatar answered Feb 02 '23 11:02

Win


I'll address only a part of your "big question", that probably will change your initial assumption:

why this tutorial didnt use dbset? why we have to create mappers?

You've missed a huge point. Check the tutorial once more and look for this piece of code:

public class Repository<T> : IRepository<T> where T : BaseEntity
{
    private readonly ApplicationContext context;
    private DbSet<T> entities;   <---- HHHEEEERRREEEE

I've marked it for you. Yes. The tutorial indeed uses DbSet<>. The fact that they wrap the dbsets into "repository" is just a convenience and formalism of onion architecture: they expose "IRepository" from the layer instead of exposing DbSets directly - just to keep the reference to EntityFramework at bay and not let any other layers know that EF is used internally. But that does not mean that they are not useing DbSets. Clearly the Repository uses DbSets.

This is because DbSet and Mappings are totally different things. The Mappings define how to map classes/properties to tables/columns and also add some metadata like which column should be not-null (= properites should be 'required'), which/what indexes to create, etc.

But all of that mappings gives you NO way to download/insert/update the records. It only defines how the database and classes look like.

For executing operations, here comes DbSet. It defines methods that operate on the data defined by mappers.

like image 36
quetzalcoatl Avatar answered Feb 02 '23 11:02

quetzalcoatl