Ehsan Ghanbari

Experience, DotNet, Solutions

What's been happened to HasMany() in Entity Framework Core

In earlier versions of Entity Framework( before Entity Framework .Core) when you wanted to create an inner table from two Entities, you would be able to use entity framework mapping in a way to create the inner table without creating a separate entity for it. For example, look at the following two classes:

 


 public class Blog

    {

        public int Id { get; set; }

 

        public string Title { get; set; }

 

        public virtual ICollection<Tag> Tags { get; set; }

    }

 

 

  public class Tag

    {

        public int Id { get; set; }

 

        public string Name { get; set; }

    

        public virtual ICollection<Blog> Blogs { get; set; }

 

    }

 

It was possible to create the inner table in the mapping of the above classes:

 

internal class BlogMapping : EntityTypeConfiguration<Blog>

    {

        public BlogMapping()

        {

            ToTable("Blog");

            HasKey(p => p.Id);

            Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

            Property(p => p.Title).IsRequired().HasMaxLength(400);

        

            HasMany(t => t.Tags).WithMany(p => p.Blogs).Map(m =>

            {

                m.MapLeftKey("BlogId");

                m.MapRightKey("TagId");

                m.ToTable("BlogTag");

            });

        }

    }

 

Now, in Entity Framework Core there is no longer the HasMany() method! It’s not supported anymore (I don't know why and I couldn't find the real reason as I personally would never have trouble with that. See here for more information) and you have to represent the many-to-many relationship by including an entity class for the join table and mapping two separate one-to-many relationships. So, firstly you have to change the Entities like below:

  

 

public class Blog

    {

        public int Id { get; set; }

 

        public string Title { get; set; }

 

        public virtual ICollection<BlogTag> BlogTags { get; set; }

    }

 

 

    public class Tag

    {

        public int Id { get; set; }

 

        public string Name { get; set; }

 

        public virtual ICollection<BlogTag> BlogTags { get; set; }

 

    }

 

    public class BlogTag

    {

        public int BlogId { get; set; }

 

        public Blog Blog { get; set; }

 

        public int TagId { get; set; }

 

        public Tag Tag { get; set; }

    }

 

Secondly, you have to map via Entity Framework Core like this:

  

 public class BlogTagMapping : IEntityTypeConfiguration<BlogTag>

    {

        public void Configure(EntityTypeBuilder<BlogTag> builder)

        {

            builder.HasOne(d => d.Blog).WithMany(e => e.BlogTags).HasForeignKey(w => w.BlogId);

            builder.HasOne(d => d.Tag).WithMany(e => e.BlogTags).HasForeignKey(w => w.TagId);

        }

    }

 

I would have seen a lot of developers writing these sort of mapping for entity framework to create inner tables, but I've hardly ever used this method, and now it seems we all have to use these ways in entity framework core!



Using In Memory Database of Entity Framework Core in asp.net core

Using the in-memory database of entity framework is super easy. Create an asp.net core and reference the following NuGet package if it's not referenced( it's been referenced in asp.net core 2 and above):

 

  • Microsoft.EntityFrameworkCore.InMemory

 

Then create the context just like the past:

 

 class SampleDbContext : DbContext

    {

        public SampleDbContext() { }

 

        public SampleDbContext(DbContextOptions<SampleDbContext> options)

        : base(options)

        { }

    }

 

And add the InMemory Configuration in ConfigureService() of startup class:

 
 

 public void ConfigureServices(IServiceCollection services)

        {

            services.Configure<CookiePolicyOptions>(options =>

            {

                // This lambda determines whether user consent for non-essential cookies is needed for a given request.

                options.CheckConsentNeeded = context => true;

                options.MinimumSameSitePolicy = SameSiteMode.None;

            });

 

            services.AddDbContext<SampleDbContext>(context => { context.UseInMemoryDatabase("Sample"); });

 

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

        }

 



About Me

Ehsan Ghanbari

Hi! my name is Ehsan. I'm a developer, passionate technologist, and fan of clean code. I'm interested in enterprise and large-scale applications architecture and design patterns and I'm spending a lot of my time on architecture subject. Since 2008, I've been as a developer for companies and organizations and I've been focusing on Microsoft ecosystem all the time. During the&nb Read More

Post Tags
Pending Blog Posts
Strategic design
Factory Pattern
time out pattern in ajax
Selectors in Jquery
Peridic pattern
How to use PagedList In asp.net MVC
How to query over Icollection<> of a type with linq
Redis as a cache server
Domain driven design VS model driven architecture
What's the DDD-lite?