Entity Framework Core странности
От: AK1977  
Дата: 06.03.19 10:33
Оценка:
Привет, ребята!
Объясните, пожалуйста, странное поведение Entity Framework Core v2.2.2
Есть класс Country, содержащий коллекцию Region, каждый Region ссылается на своего владельца — Country, и может так же иметь коллекцию SubRegions, причем каждый SubRegion ссылается на свой SuperiorRegion.
Код:
    public class Country
    {
        public Country(string name)
        {
            Name = name;
            Regions = new List<Region>();
        }
 
        // for EF
        protected Country()
        {
        }
 
        public int Id { get; set; }
 
        public string Name { get; set; }
 
        public IList<Region> Regions { get; set; }
 
        public Region CreateRegion(string name)
        {
            var region = new Region(name, this);
 
            Regions.Add(region);
 
            return region;
        }
    }

    public class Region
    {
        public Region(string name, Country country)
        {
            Name = name;
            Country = country;
            SubRegions = new List<Region>();
        }
 
        // for EF
        protected Region()
        {
        }
 
        public int Id { get; set; }
 
        public string Name { get; set; }
 
        public Country Country { get; set; }
 
        public IList<Region> SubRegions { get; set; }
 
        public Region SuperiorRegion { get; set; }
 
        public Region CreateSubRegion(string name)
        {
            var region = new Region(name, Country);
 
            SubRegions.Add(region);
            region.SuperiorRegion = this;
 
            return region;
        }
    }


Далее я конструирую из них дерево (пока все идет хорошо):

    var country = new Country("Best Country of the World");
    var beachesRegion = country.CreateRegion("Region with beaches");
        var hotelsRegion = beachesRegion.CreateSubRegion("Region with hotels");
        var workRegion = country.CreateRegion("Region with hard work");


Проверяем
Console.WriteLine(country.Regions.Count); // 2


А вот теперь интереснее.
Создаю DbContext…
    public class CountryContext : DbContext
    {
        public CountryContext(DbContextOptions options) : base(options)
        {
        }
 
        public DbSet<Country> Countries { get; set; }
 
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
        }
    }


… и подключаю к нему Country:

    var options = new DbContextOptionsBuilder<CountryContext>()
            .UseInMemoryDatabase(databaseName: "Countries")
            .Options;

        using (var db = new CountryContext(options))
        {
            db.Countries.Add(country);
        }

И в этот момент
Console.WriteLine(country.Regions.Count); //3!!!!!!!

То есть все Region подсоединились напрямую к Country.

Собственно, вопрос: как мне сделать так, чтобы SubRegion не добавлялся в коллекцию Regions у Country?
Re: Entity Framework Core странности
От: BlackEric http://black-eric.lj.ru
Дата: 07.03.19 14:22
Оценка:
Здравствуйте, AK1977, Вы писали:

AK>[cs]

AK> using (var db = new CountryContext(options))
AK> {
AK> db.Countries.Add(country);
AK> }

AK>То есть все Region подсоединились напрямую к Country.


AK>Собственно, вопрос: как мне сделать так, чтобы SubRegion не добавлялся в коллекцию Regions у Country?


Подгружайте только то что нужно. Не делайте Add
https://github.com/BlackEric001
Re: Entity Framework Core странности
От: GlebZ Россия  
Дата: 09.03.19 08:38
Оценка:
Здравствуйте, AK1977, Вы писали:


AK>Собственно, вопрос: как мне сделать так, чтобы SubRegion не добавлялся в коллекцию Regions у Country?

Тебе вообще не сохранять в хранилище или как? Если не сохранять то убери set из проперти. Если нет, то курить EntityState Detach https://docs.microsoft.com/ru-ru/ef/ef6/saving/change-tracking/entity-state
Re: Entity Framework Core странности
От: stapter  
Дата: 09.03.19 10:43
Оценка:
Здравствуйте, AK1977, Вы писали:

AK>Собственно, вопрос: как мне сделать так, чтобы SubRegion не добавлялся в коллекцию Regions у Country?


Никаких странностей здесь нет.
В методе CreateSubRegion Вы сами добавляете связь Country с SubRegion: new Region(name, Country);
Причина различного поведения в представленных вариантах заключается в том, что при хранении данного "дерева" в коллекциях, у Вас сохраняется ссылка на объект Country в Region, а при хранении этого же дерева в БД, создается еще одна связь записи Region с записью Country в двух направлениях (как при добавлении нового Region, так и при добавлении нового SubRegion).
Выхода два: либо создать отдельную сущность SubRegion, убрав из него референс на Country (не забыв при этом для Region'a и SubRegion'a реализовать общий интерфейс IRegion (без Country)), либо оставить так как есть, сделав связь между Region и Country необязательной, то есть в методе CreateRegion регион будет создаваться как и раньше: new Region(name, Country), а в методе CreateSubRegion будет просто new Region(name). Я бы для себя предпочел первый вариант.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.