Base solution for your next web application
Starts in:
01 DAYS
01 HRS
01 MIN
01 SEC
Open Closed

Issue saving many to many child items #1189


User avatar
0
soulmate created

Hello, I hove following entities:

public class Provider : EntityBase
    {

        [Column(Order = 120)]
        public string Name { get; set; } 

        public virtual ICollection<Country> Countries { get; set; }

    }

    public class Country :EntityBase
    {
        [MaxLength(100)]
        public string Name { get; set; }

        [MaxLength(10)]
        public string Code { get; set; }

        
    }

And following configuration:

public class ProviderConfiguration : EntityTypeConfiguration<Provider>
    {
        public ProviderConfiguration()
        {
            HasMany(m => m.Countries)
                .WithMany()
                .Map(m =>
                {
                    m.MapLeftKey("ProviderId");
                    m.MapRightKey("CountryId");
                    m.ToTable("Provider_Countries");
                });
        }
    }

That means a provider can have several countries. The table in sql server look good and as far as I know that is the recommended method to build up many to many relationship. However, when I try to save the children only my provider entity is saved and the children are not saved to the "Provider_Countries" table:

public ProviderService(IRepository<Provider> providerRepository, IRepository<Country> countryRepository)
        {
            _providerRepository = providerRepository;
            _countryRepository = countryRepository;
        }
 

public async Task SaveAsync(Provider provider)
        {
            var entity = provider;


            var countriesToAdd = provider.Countries.ToList();

            //Clear existing entities
            entity.Countries.Clear();


            foreach (var countryToAdd in countriesToAdd)
            {
                var country = _countryRepository.Get(countryToAdd.Id);

                entity.Countries.Add(country);
            }
            _providerRepository.InsertOrUpdate(entity);


          
                await CurrentUnitOfWork.SaveChangesAsync();
         
        }

Based on the topics I found on the internet that is the recommended approach how to save a many to many relationship. Do you have any idea how I can save the child items?


10 Answer(s)
  • User Avatar
    0
    patrickglaudemans created

    Hi,

    In your scenario it should be enough to define property public virtual ICollection<Country> Countries { get; set; } in Provider class and public virtual ICollection<Provider> Providers { get; set; } in Country class

    EF will setup an extra link table by itsself and you're able to add many countries to provider and many providers to country just by adding them in the collection normally save them.

  • User Avatar
    0
    soulmate created

    Hey, Thank you for your reply. I already had a working provider configuration:

    using System.Data.Entity.ModelConfiguration;
    
    namespace Entities
    {
        public class ProviderConfiguration : EntityTypeConfiguration<Provider>
        {
            public ProviderConfiguration()
            {
          
        HasMany(c => c.Countries).WithMany(i => i.Providers)
        .Map(t => t.MapLeftKey("ProviderId")
            .MapRightKey("CountryId")
            .ToTable("Providers_Countries"));
    
             
            }
        }
    }
    

    However, I deleted the configuration to follow your sugesstions. The database structure looks good for me (see attachment). However, I still cant save entities :(

  • User Avatar
    0
    patrickglaudemans created

    Hi,

    what code do you use to actually add the objects?

  • User Avatar
    0
    soulmate created

    I have a SaveAsync method that accepts the provider entity and adds countries here

    public async Task SaveAsync(Provider provider)
            {
                var entity = provider;
    
    
                var countriesToAdd = provider.Countries.ToList();
    
                //Clear existing entities
                entity.Countries.Clear();
    
    
                foreach (var countryToAdd in countriesToAdd)
                {
                    var country = _countryRepository.Get(countryToAdd.Id);
    
                    entity.Countries.Add(country);
                }
                _providerRepository.InsertOrUpdate(entity);
    
    
              
                    await CurrentUnitOfWork.SaveChangesAsync();
             
            }
    
  • User Avatar
    0
    patrickglaudemans created

    Hi,

    Don't see any shortcomings in your code.

    I'have the same issue for one of my other entities with two many to many relations. One list got saved and the other does not! Check: [http://forum.aspnetboilerplate.com/viewtopic.php?f=5&t=2458&p=5695&hilit=many#p5695])

    Perhaps hikalkan can help us out!

  • User Avatar
    0
    hikalkan created
    Support Team

    Hi,

    First of all, your code seems strange to me.

    You are getting countries from same entity, then adding to the same entity again. What's purpose of that? Also, is that a domain service or app service?

  • User Avatar
    0
    soulmate created

    Hi, Yes, in controller the countries are added. This was just a test. I rewrite the test code, in following scenario a country with id 2 is loaded. However, the mapping is still not saved:

    public async Task SaveAsync(IProvider provider, bool saveChanges = true)
            {
                var entity = provider as Provider;
    
                if (entity == null)
                    throw new ArgumentNullException(nameof(provider));
    
    
                //Clear existing entities
                entity.Countries= new List<Country>();
    
    
                    var country = _countryRepository.Get(2);
    
                    entity.Countries.Add(country);
            
                _providerRepository.InsertOrUpdate(entity);
    
    
                if (saveChanges)
                {
                 
    
                    await CurrentUnitOfWork.SaveChangesAsync();
                }
            }
    
  • User Avatar
    0
    soulmate created

    Hey Hikalkan,

    since Patrick also has this problem: Is this maybe a general problem with automatic generated mapping entities? Do you have any idea how to track this one?

    Thank you!

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Can you share your EntityBase class as well. Because I have tried your first schenario by replacing EntityBase with Entity, it worked for me.

  • User Avatar
    0
    soulmate created

    Thanks. That solved my problem