Entity Framework: установить свойство навигации с помощью локального объекта (еще не сохранено в базе данных) - PullRequest
0 голосов
/ 20 января 2019

Я использую Entity Framework версии 6 и мне нужно массово вставить тысячи объектов в базу данных за очень короткий период времени.

Поэтому я изменил DbContext.Configuration.AutoDetectChangesEnabled на false и использую SaveChanges только после множества добавленных элементов.

Сущность, назовем ее Person, имеет свойство навигации, т.е. г. Supervisor.

Теперь я хочу добавить человека в базу данных и заполнить свойство навигации супервизором, который был добавлен в контекст (только локальный, а не в базе данных) итерацией до этого.

Я просто вызываю SaveChanges () после 2000 тысяч человек из-за производительности. Если я смотрю в базу данных после SaveChanges, столбец Supervisor всегда равен NULL Как добавить свойство навигации?

Как ни странно, моя модель сущности имеет четыре навигационных свойства с именами Supervisor1, Supervisor2, Supervisor11 и Supervisor3. Почему модель сущностей создает четыре свойства навигации для одного ограничения базы данных?

Чтобы объяснить мою проблему подробно: это мой структура базы данных . EntityFramework создает этой модели .

Существует цикл для обработки данных из файла CSV:

     db.DbContext.Configuration.AutoDetectChangesEnabled = false; // for performance
    ///...    
    while (!parser.EndOfData)
    {                  
    // process data from a csv file with a name and a supervisorId             
        db.AddNewPerson(name, supervisorId);
    }
    db.SaveChanges();
    db.DbContext.Configuration.AutoDetectChangesEnabled = true;

И это метод уровня доступа к данным:

public void AddNewPerson(string name, long? supervisorId)
    {
        var dbSetPerson = dbContext.Set<Person>();
        var newPerson = new Person(name);
        dbSetPerson.Add(newPerson);

        if (supervisorId != null)
        {
            var supervisor = dbSetPerson.Local.FirstOrDefault(x => x.PersonId == supervisorId); // first look if the supervisor was just processed in this loop
            if (supervisor == null)
                supervisor = dbSetPerson.FirstOrDefault(x => x.PersonId == supervisorId); // if the was no person found look in the database
            if (supervisor != null)
                newPerson.Person2 = supervisor;
        }
    }

Заранее спасибо за помощь!

1 Ответ

0 голосов
/ 20 января 2019

Я думаю, что ваша проблема в том, что на данном этапе сущность не сохраняется в базе данных, а EF (прокси) не знает об этом.Что вы можете сделать, это прикрепить его после того, как вы вызвали StoreChanges ():

yourContext.Persons.Attach(justAddedPerson);

Но когда вы добавите некоторый код, я могу дать более конкретный ответ.

ОБНОВЛЕНИЕ На основании ваших правок (я полагаю, что идентификаторы являются int, а не созданы автоматически), я бы предложил следующее:

var persons = new List<Person>();
while (!parser.EndOfData)
{
    var person = new Person { Name = parser... }
    person.SupervisorId = parser...
    list.Add(person);
}

dbSet.AddRange(persons);

dbContext.SaveChanges();

Сначала выполните синтаксический анализ, а затем операции db.EF достаточно умен, чтобы устанавливать свойства навигации, когда вы не изменяете конфигурацию, и в этом больше нет необходимости, потому что AddRange () должен быть намного быстрее, чем Add (), так как он вызывает детектор изменений только один раз.Устанавливая только идентификатор супервизора,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...