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

ользую MVC 3, EF 4.1 и dbContext. Мне нужно знать, как удалить сущность в отношении один-ко-многим с ненулевым внешним ключом.

Когда я удаляю дочернюю сущность и выполняю SaveChanges, я получаю ошибку:

Операция не выполнена: отношение не может быть изменено, так как одно или несколько свойств внешнего ключа не могут иметь значение NULL. Когда в отношение вносится изменение, для соответствующего свойства внешнего ключа устанавливается нулевое значение. Если внешний ключ не поддерживает нулевые значения, необходимо определить новое отношение, свойству внешнего ключа должно быть назначено другое ненулевое значение или несвязанный объект должен быть удален.

Из других постов я понимаю, что использование Remove (entity) помечает сущность для удаления. Во время SaveChanges EF устанавливает для внешнего ключа значение Null, и возникает вышеуказанная ошибка.

Я нашел несколько сообщений, которые используют DeleteObject для дочерней сущности, а не Remove; однако подход DeleteObject, похоже, был отброшен из-за добавления в dbContext и DbSet.

Я нашел сообщения, которые предлагают изменить отношение внешнего ключа EDMX к Nullable. Модификация EDMX - это хорошо, но всякий раз, когда выполняется Обновление модели для базы данных, эти изменения сбрасываются со счетов и должны применяться повторно. Не оптимально

В другом посте предлагалось создать прокси-объект с отношениями внешних ключей, установленными в Nullable, но я не понимаю такой подход. Кажется, он страдает от той же проблемы, что и изменение EDMX, в том смысле, что контекст автоматически обновляется при сохранении изменений в EDMX.

Моя упрощенная модель:

public partial class User
{
    public User()
    {
        this.UserContacts = new HashSet<UserContact>();
    }

    public long userId { get; set; }
    public string userEmail { get; set; }
    public string userPassword { get; set; }
    public string userFirstName { get; set; }
    public string userLastName { get; set; }
     . . .
    public virtual Country Country { get; set; }
    public virtual State State { get; set; }
    public virtual ICollection<UserContact> UserContacts { get; set; }
}

}

public partial class UserContact
{
    public long userContactId { get; set; }
    public long userContactUserId { get; set; }
    public long userContactTypeId { get; set; }
    public string userContactData { get; set; }

    public virtual ContactType ContactType { get; set; }
    public virtual User User { get; set; }
}

UserContactUserId и userContactTypeId являются обязательными внешними ключами.

В контейнере dbContext и Users, и UserContact являются DbSet.

У меня есть ViewModel для пользователя и ViewModel для UserContact следующим образом

public class UserContactViewModel
{
    [HiddenInput]
    public long UserContactId { get; set; }

    [HiddenInput]
    public long UserContactUserId { get; set; }

    [Display(Name = "Contact")]
    [Required]
    public string ContactData { get; set; }

    [Required]
    public long ContactType { get; set; }

    [HiddenInput]
    public bool isDeleted { get; set; }

}

    public class MyProfileViewModel
    {

        [HiddenInput]
        public long UserId { get; set; }

        [Required]
        [Display(Name = "First Name")]
        [StringLength(100)]
        public string FirstName { get; set; }

        [Required]
        [StringLength(100)]
        [Display(Name = "Last Name")]
        public string LastName { get; set; }
        ....
        public IEnumerable<UserContactViewModel> Contacts { get; set; }

}

При сохранении изменений в профиле пользователя я перебираю список сущностей UserContactViewModel, чтобы определить, какие из них были добавлены, изменены или удалены.

                    foreach (var c in model.Contacts)
                    {
                        UserContact uc = usr.UserContacts.Single(con => con.userContactId == c.UserContactId);
                        if (uc != null)
                        {
                            if (c.isDeleted == true)  // Deleted UserContact
                            {
                                ctx.UserContacts.Remove(uc);  // Remove doesn't work
                            }
                            else  //  Modified UserContact
                            {
                                uc.userContactData = c.ContactData;
                                uc.userContactTypeId = c.ContactType;
                                ctx.Entry(uc).State = EntityState.Modified;
                            }
                        }
                        else  // New UserContact
                        {
                            usr.UserContacts.Add(new UserContact { userContactUserId = model.UserId, userContactData = c.ContactData, userContactTypeId = c.ContactType });
                        }
                    }

Буду признателен за любую помощь.

Ответы на вопрос(4)

Ваш ответ на вопрос