Попытка понять, почему состояние дочернего объекта не изменяется при изменении состояния родительского объекта - PullRequest
0 голосов
/ 07 января 2020

Вот так выглядит моя модель:

A Branch принадлежит Organisation. Organisation принадлежит объекту User:

[Table("branch")]
public class Branch
{
    public long BranchId { get; set; }

    public string BranchName { get; set; }

    public long OrganisationId { get; set; }

    [ForeignKey("OrganisationId")]
    public Organisation Organisation { get; set; }
}

[Table("organisation")]
public class Organisation
{
    public long OrganisationId { get; set; }

    public string OrganisationName { get; set; }

    public long UserId { get; set; }

    [ForeignKey("UserId")]
    public UserProfile UserProfile { get; set; }
}

[Table("userprofileview")] // <-- UserProfile is representing a view 
public class UserProfile
{
    public long UserId { get; set; }

    public string Name { get; set; }
}

UserProfile, представляющему представление, и его нельзя вставить (поскольку он имеет левое соединение).

Я хочу добавить новый Branch к существующему Organisation (который принадлежит существующему User), следующий код выдает мне ошибку:

public void AddOrUpdateBranchAsAdminUser(Branch branch)
{
    if (branch.BranchId > 0)
    {
        // code to update branch
    }
    else
    {
        _context.Branch.Add(branch);
        _context.Entry(branch.Organisation).State = EntityState.Unchanged; // <-- Don't update Organisation 
        /*
         * uncommenting this line will fix the problem
         * _context.Entry(branch.Organisation.UserProfile).State = EntityState.Unchanged;  
         */
        _context.SaveChanges();
    }
}

This это ошибка, которую я получаю:

Целевая таблица userprofileview INSERT не вставляется в

Если я раскомментирую строку, которая устанавливает состояние UserProfile то работает нормально ... Кто-нибудь может объяснить такое поведение? Я ожидал бы, что изменение состояния Organisation (родительской сущности) также должно изменить состояние UserProfile.

1 Ответ

0 голосов
/ 07 января 2020

Это происходит из-за кэширования Entity Framework.

Получаемое сообщение

Просмотр профиля пользователя из целевой таблицы INSERT не вставляется в

Вы получаете это, потому что, как вы сказали,

Объект UserProfile представляет представление и не может быть вставлен (поскольку имеет левое соединение).

Кажется, это пока что имеет смысл ...

После удаления строки

_context.Entry(branch.Organisation.UserProfile).State = EntityState.Unchanged;

Вы помечаете кэшированную запись как неизменную. Это означает, что при сохранении SaveChanges () Entity Framework НЕ будет пытаться произвести sh обновление этой записи в базе данных. Я не могу ответить, КАК UserProfile "трогается", но у вас есть атрибут

[ForeignKey("UserId")]

в организации. У меня есть ощущение, что, поскольку вы изменяете объект Organization, Entity Framework пытается «коснуться» всех дочерних объектов. Кажется, это как-то генерирует «Вставку» в профиле пользователя. Ваше исправление состоит в том, чтобы установить для объекта значение «Без изменений», чтобы структура сущностей никогда не пыталась внести sh какие-либо изменения в эту таблицу.

Редактировать: возможно, я смогу объяснить это поведение, если 1) вы создадите новую ветвь , 2) Свяжите организацию с филиалом, которого нет в кэше EF. 3) Связанная организация имеет профиль пользователя, которого нет в кэше EF. Я думаю, что если вы сгенерировали ветку в этой ситуации, EF автоматически попытается сериализовать ваши связанные объекты и вставить их в базу данных.

Вы можете сломать этот шаблон, если вы изменили свои классы, подобные

[Table("branch")]
public class Branch
{
    public long BranchId { get; set; }

    public string BranchName { get; set; }

    public long OrganisationId { get; set; }
}
public class BranchComposite
{
    public Branch Branch { get; set; }
    [ForeignKey("OrganisationId")]
    public Organisation Organisation { get; set; }
}
...