Ссылка на объекты:Смешанный граф сущностей, EntityKeys, Присоединенных и Новых объектов

StackOverflow https://stackoverflow.com/questions/1628626

Вопрос

В моей модели данных у меня есть довольно распространенное разделение между моими объектами / таблицами / данными:

  • "Транзакционные" сущности, которые представляют работу, выполняемую системой.Эти объекты создаются системой и важны только в определенных контекстах.Они регулярно создаются "на лету".(В сторону:Есть ли подходящее название для этого типа сущности?)
  • Объекты "Словаря данных", которые представляют общие свойства транзакционных объектов.Они определяются нерегулярно (в основном в начале проекта) и имеют гораздо более статичный жизненный цикл.Как правило, они создаются мной.

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

Я хочу (жестко) закодировать ссылки на экземпляры объектов словаря данных в свой код.Это дает мне возможность кодировать бизнес-логику с помощью простого для понимания языка.(Так, например, у меня мог бы быть пользовательский тип "Plain" и пользовательский тип "Admin", а затем правило, которое гласит "разрешать доступ, только если пользовательский тип пользователя равен Admin").

Я использую LINQ-to-Entities в качестве моей технологии доступа к данным / ORM.Чтобы реализовать ссылки на словарь данных, я сохраняю EntityKeys .Насколько я понимаю, они оторваны от контекста объекта и поэтому подходят для этой цели.(Поскольку они не содержат состояния объекта, мне также не нужно беспокоиться о том, что это состояние устареет.)

Однако это вызывает у меня проблемы, когда я пытаюсь добавить новую транзакционную сущность с помощью DD-EntityKey-reference .Продолжая мой пример, я делаю это:

UserEntities userEntities = new UserEntitites()
User user = new User()
user.UserType = new UserType()
user.UserType.EntityKey = adminEntityKey
userEntities.AddToUser(user)

...и это выдает мне следующую ошибку:

Система.Исключение InvalidOperationException :Объект не может быть добавлен в ObjectStateManager, поскольку у него уже есть EntityKey .Используйте ObjectContext.Прикрепить, чтобы прикрепить объект, у которого есть существующий ключ.

Если я попытаюсь вызвать userEntities.Attach(user) вместо AddToUser , я получу это:

Система.Исключение InvalidOperationException :Объект с нулевым значением EntityKey не может быть присоединен к контексту объекта.

Обе эти ошибки имеют смысл, учитывая смешивание новых и ранее существовавших объектов, которое я делаю.В чем я не уверен, так это в том, как обойти эту проблему.Есть ли какой-нибудь способ, которым я могу отсоединить ссылки на DD-объекты и назначить их новым присоединенным объектам, не требуя от меня загрузки всего состояния DD-объекта?

Это было полезно?

Решение

Я попытаюсь объяснить, почему вы получаете эти исключения:

Система.Исключение InvalidOperationException :Объект не может быть добавлен в ObjectStateManager, поскольку у него уже есть EntityKey .Используйте ObjectContext.Прикрепить, чтобы прикрепить объект, у которого есть существующий ключ.

Создаются новые объекты User и UserType.Ключ EntityKey для UserType был установлен, но когда вы передаете его в userEntities.Add() EF пытается присвоить им статус ДОБАВЛЕННЫХ.Поскольку UserType имеет EntityKey, EF понимает, что что-то не так, и выдает исключение.

Система.Исключение InvalidOperationException :Объект с нулевым значением EntityKey не может быть присоединен к контексту объекта.

В этом исключении с UserType все в порядке, но исключение выдается из-за того, что пользовательская сущность - у нее нет EntityKey и, следовательно, она не может быть присоединена.

Вот как я бы решил эту проблему (если, как вы говорите, жесткое кодирование ссылок на словарь данных в порядке):

Для объекта UserType я бы создал статические ссылки на идентификаторы UserType:

public partial class UserType
    {
        public const int AdminUserTypeID = 1;
        public const int PlainUserTypeID = 2;
    }  

В пользовательском объекте было бы свойство extender для облегчения доступа к внешнему ключу UserType:

public partial class User
{
    public int? UserTypeID
    {
        set
        {
           UserTypeReference.EntityKey = new EntityKey("UserEntities.UserType", "UserTypeID", value);
        }
        get
        {
            if (UserTypeReference.EntityKey == null)
                return null;

            if (UserTypeReference.EntityKey.EntityKeyValues.Count() > 0)
                return (int)UserTypeReference.EntityKey.EntityKeyValues[0].Value;
            else
                return null;
        }
    }
}

Наконец, вариант использования для создания нового пользователя будет выглядеть следующим образом:

using(UserEntities userEntities = new UserEntitites())
{
    User user = new User();
    user.UserTypeID = UserType.AdminUserTypeID;
    userEntities.AddToUser(user);
    userEntities.SaveChanges()
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top