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)
-
0
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.
-
0
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 :(
-
0
Hi,
what code do you use to actually add the objects?
-
0
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(); }
-
0
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!
-
0
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?
-
0
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(); } }
-
0
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!
-
0
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.
-
0
Thanks. That solved my problem