Проблемы с Entity Framework

Я пытаюсь добавить ProfileProperty в таблицу ProfileProperties, используя ObjectContext.AddObject.

Поля db для таблицы ProfileProperties:

ProfilePropertyID
ProfilePropertyDefinitionID
UserID
PropertyValue

Поля db для таблицы ProfilePropertyDefinitions:

ProfilePropertyDefinitionID
PropertyName

Переменные для передаваемого объекта ProfileProperty:

ProfilePropertyID
ProfilePropertyDefinition
User
PropertyValue

И ProfilePropertyDefinitionID, и UserID являются внешними ключами, поэтому после создания объекта ProfileProperty я выбираю User и ProfilePropertyDefinition из их таблиц, чтобы заполнить ProfileProperty связанными объектами.

Затем, когда я пытаюсь AddObject передать объект с этими переменными, я получаю сообщение об ошибке:

InnerException = {"Невозможно вставить значение NULL в столбец 'PropertyName', таблица 'mydbserver.dbo.ProfilePropertyDefinitions'; столбец не допускает пустых значений. Ошибка INSERT.\r\nВыполнение оператора завершено."}

Я сделал перерыв, чтобы проверить, что держит объект, который я передал, и он имеет это:

ProfilePropertyID = -1
ProfilePropertyDefinition = 
    { ProfilePropertyDefinitionID = 3
      PropertyName = "First Name" }
User = /*Not going  to put details here, but assume the user object is there*/
PropertyValue = "Matt"

Вопросы

  1. Почему говорят, что PropertyName равно нулю, когда оно есть?
  2. Почему он вообще пытается добавить объект ProfilePropertyDefinition в таблицу ProfilePropertyDefinitions? (Я не хочу, чтобы он добавлял или обновлял связанные объекты)

Сервисный уровень AddProfile()

public int AddProfile(ProfilePropertyViewModel property)
{
    int objId = -1;
    ProfileProperty profile = null;

    if (ValidateProfile(property))
    {
        try
        {
            using (DbTransaction transaction = _profileRepository.BeginTransaction())
            {
                profile = ProfilePropertyTranslator.ViewToDomain(property);
                profile.User = _userRepository.SelectByKey(UserColumns.UserName, property.UserName);
                profile.ProfilePropertyDefinitionReference.EntityKey = new EntityKey("GraffytysDBEntities.ProfilePropertyDefinition", "ProfilePropertyDefinitionID", property.ProfilePropertyDefinitionID);

                _profileRepository.Add(profile);
                if (_profileRepository.Save() >= 0)
                {
                   transaction.Commit();
                   objId = property.ProfilePropertyId;
                }
            }
        }
        catch(Exception ex)
        {
            throw ex;
        }
    }

    return objId;
 }

Репозиторий Add():

    public void Add(E entity)
    {
        _ctx.AddObject(entity.GetType().Name, entity);
    }

person Matt    schedule 03.01.2010    source источник
comment
Итак, вы создаете новый ProfileProperty с существующими User и ProfilePropertyDefinition. Выбираете ли вы существующие объекты из того же контекста, в котором вы вызываете AddObject?   -  person Sander Rijken    schedule 03.01.2010
comment
Вы можете попробовать изменить код и установить ProfilePropertyDefinitionReference.EntityKey и UserReference.EntityKey. Вам не нужно будет сначала выбирать его из БД, и это, вероятно, решит вашу проблему.   -  person LukLed    schedule 03.01.2010
comment
@LukLed, можете ли вы привести пример этого в ответе (чтобы за него можно было проголосовать / принять)?   -  person Sander Rijken    schedule 03.01.2010
comment
Да они все из одного контекста.   -  person Matt    schedule 03.01.2010
comment
Что делает ProfilePropertyTranslator.ViewToDomain(property)?   -  person LukLed    schedule 04.01.2010
comment
Принимает ProfilePropertyViewModel и создает новый объект ProfileProperty, используя его содержимое. ViewModel — это плоская версия (не содержит связанных объектов) версии DomainModel — ProfileProperty   -  person Matt    schedule 04.01.2010
comment
Попробуйте использовать ту же функцию, но не используйте ProfilePropertyViewModel и ProfilePropertyTranslator, просто создайте ProfileProperty вручную и проверьте, работает ли она. Возьмите примеры значений User и ProfileProperty.   -  person LukLed    schedule 04.01.2010
comment
Я поставил точку останова сразу после транслятора, чтобы убедиться, что объект создан правильно. Все, что он делает, это берет значения и создает из них объект, точно так же, как если бы я сделал new ProfileProperty(/* мои значения здесь */)   -  person Matt    schedule 04.01.2010
comment
Просто напишите простейшую функцию, добавляющую ProfileProperty. Не используйте ProfilePropertyViewModel, не используйте ProfilePropertyTranslator. Это работает?   -  person LukLed    schedule 04.01.2010
comment
Да, это так! У меня была ошибка в моем переводчике, он создает новый объект ProfilePropertyDefinition, чтобы заполнить его место. Спасибо!   -  person Matt    schedule 04.01.2010


Ответы (1)


Это, вероятно, решит вашу проблему и является более эффективным способом установки свойств внешнего ключа:

profileProperty.ProfilePropertyDefinitionReference.EntityKey = new EntityKey("MyEntities.ProfilePropertyDefinitions", "ProfilePropertyDefinitionID", 3);

Вы должны заменить «MyEntities» на имя вашей модели БД.

Вы также можете проверить, добавляете ли вы ProfilePropertyDefinition к ObjectContext где-то еще в коде. Проблема может быть в этом, а не в этой части кода.

person LukLed    schedule 03.01.2010
comment
Вы уверены, что не добавляете ничего другого, используя тот же ObjectContext? Возможно, вы добавляете еще один ProfilePropertyDefinition к тому же ObjectContext, и это выдает ошибку. Проверьте это перед вызовом SaveChanges. Проверьте, содержат ли ProfilePropertyDefinitions новые строки. - person LukLed; 03.01.2010
comment
Так не должно быть... Только что проверил, новых строк нет. Вот код в том месте, где я вызываю добавление в репозиторий: _profileRepository.Add(property); if(_profileRepository.Save() ›= 0) { transaction.Commit(); } - person Matt; 04.01.2010
comment
ХОРОШО. Не могли бы вы вставить весь код? Вы также можете посмотреть профилировщик SQL и посмотреть, как на самом деле называется sql. Помните, что вам не нужно вызывать _repository.Add(...), чтобы вставить объект в ObjectContext. Если новый объект связан с другим объектом, который вы добавили в ObjectContext с помощью _repository.Add(...), он тоже будет добавлен. - person LukLed; 04.01.2010