Pergunta

No meu modelo de dados Eu tenho uma divisão bastante comum entre os meus objetos / mesas / dados:

  • entidades "transacionais" que representam o trabalho que está sendo feito pelo sistema. Estas entidades são criadas pelo sistema e só são importantes em contextos específicos. Eles são regularmente criados em tempo real. (Aparte:? Existe um nome próprio para este tipo de entidade)
  • "Dicionário de Dados" entidades que representam as propriedades comuns das entidades transacionais. Estes são definidos de forma irregular (principalmente no início do projeto) e têm um ciclo de vida muito mais estática. Eles são tipicamente criados por mim.

Assim, por exemplo, eu poderia ter um usuário entidade (transacional) e uma entidade UserType (dicionário de dados).

Eu quero referências de código (hard) para instâncias das entidades Dicionário de Dados em meu código. Isso me dá a capacidade de lógica de negócios de código com uma linguagem fácil de entender. (Assim, por exemplo, eu poderia ter um UserType de "Plain" e um UserType de "Admin", e em seguida, uma regra que diz que "permitir o acesso apenas se UserType do Usuário é igual a Admin").

Eu estou usando LINQ to Entities como meu tecnologia de acesso de dados / ORM. Para implementar as referências Dicionário de Dados, eu estou armazenando EntityKeys. O meu entendimento é que eles estão separados do contexto do objeto e assim são adequados para esta finalidade. (Como eles não contêm estado entidade, eu também não tem que se preocupar com isso obsoleto indo estado.)

No entanto, isso está me dando problemas ao tentar adicionar uma nova entidade transacional com uma-EntityKey referência DD. Continuando meu exemplo, eu estou fazendo isso:

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

... e isso me dá o seguinte erro:

System.InvalidOperationException: O objeto não pode ser adicionado ao ObjectStateManager porque ele já tem um EntityKey. Use ObjectContext.Attach para anexar um objeto que tem uma chave existente.

Se eu tentar chamar userEntities.Attach (usuário) em vez de AddToUser, fico com esta:

System.InvalidOperationException:. Um objeto com um valor nulo EntityKey não pode ser ligado a um contexto de objeto

Ambos estes erros faz sentido, dada a mistura de entidades novas e pré-existentes que eu estou fazendo. O que eu não estou certo sobre é como contornar este problema. Existe alguma maneira eu posso ter destacado referências a DD-entidades e atribuí-los a novos objetos ligados sem necessidade de me para carregar todo o estado DD-entidade?

Foi útil?

Solução

Vou tentar explicar por que você está recebendo as seguintes exceções:

System.InvalidOperationException: O objeto não pode ser adicionado ao ObjectStateManager porque ele já tem um EntityKey. Use ObjectContext.Attach para anexar um objeto que tem uma chave existente.

entidades

novo usuário e usertype são criados. O EntityKey em UserType foi definido, mas quando você passá-lo para userEntities.Add () EF tenta definir-lhes o estatuto ADICIONADO. Desde UserType tem uma EntityKey EF percebe que algo está errado e lança exceção.

System.InvalidOperationException:. Um objeto com um valor nulo EntityKey não pode ser ligado a um contexto de objeto

Neste exceção está tudo ok com UserType, mas a exceção é lançada porque entidade de usuário -. Não tem EntityKey e, portanto, não pode ser anexado

Isto é como eu iria resolver este problema (se, como você diz, hardcoding de dados referências dicionário é ok):

entidade Em UserType eu iria criar referências estáticas para UserType ID de:

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

Na entidade User haveria extensor de propriedade para um acesso mais fácil à chave estrangeira 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;
        }
    }
}

Finalmente, o caso de uso para a criação de novo usuário ficaria assim:

using(UserEntities userEntities = new UserEntitites())
{
    User user = new User();
    user.UserTypeID = UserType.AdminUserTypeID;
    userEntities.AddToUser(user);
    userEntities.SaveChanges()
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top