Pregunta

En mi modelo de datos tengo una división bastante común entre mis objetos / tablas / datos:

  • " Transaccional " entidades que representan el trabajo que está haciendo el sistema. Estas entidades son creadas por el sistema y solo son importantes en contextos específicos. Se crean regularmente sobre la marcha. (Aparte: ¿Hay un nombre propio para este tipo de entidad?)
  • " Diccionario de datos " entidades que representan propiedades comunes de las entidades transaccionales. Estos se definen de manera irregular (principalmente al comienzo del proyecto) y tienen un ciclo de vida mucho más estático. Por lo general, los creo yo.

Entonces, por ejemplo, podría tener una entidad User (transaccional) y una entidad UserType (diccionario de datos).

Quiero codificar referencias (duras) a instancias de las entidades del Diccionario de datos en mi código. Esto me da la capacidad de codificar la lógica empresarial con un lenguaje fácil de entender. (Entonces, por ejemplo, podría tener un UserType de '' Plain '' y un UserType de '' Admin '', y luego una regla que dice '' permitir el acceso solo si el UserType del usuario es igual a Admin '').

Estoy usando LINQ-to-Entities como mi tecnología de acceso a datos / ORM. Para implementar las referencias del Diccionario de datos, estoy almacenando EntityKeys. Tengo entendido que están separados del contexto del objeto y, por lo tanto, son adecuados para este propósito. (Como no contienen estado de entidad, tampoco tengo que preocuparme de que ese estado se vuelva obsoleto).

Sin embargo, esto me está dando problemas cuando intento agregar una nueva entidad transaccional con una referencia DD-EntityKey. Continuando con mi ejemplo, estoy haciendo esto:

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

... y esto me da el siguiente error:

  

System.InvalidOperationException: el objeto no se puede agregar a ObjectStateManager porque ya tiene una EntityKey. Use ObjectContext.Attach para adjuntar un objeto que tenga una clave existente.

Si intento llamar a userEntities.Attach (usuario) en lugar de AddToUser, obtengo esto:

  

System.InvalidOperationException: un objeto con un valor EntityKey nulo no se puede adjuntar a un contexto de objeto.

Ambos errores tienen sentido, dada la combinación de entidades nuevas y preexistentes que estoy haciendo. Lo que no estoy seguro es cómo solucionar este problema. ¿Hay alguna manera de que pueda tener referencias separadas a entidades DD y asignarlas a nuevos objetos adjuntos sin requerir que cargue todo el estado de la entidad DD?

¿Fue útil?

Solución

Trataré de explicar por qué recibes estas excepciones:

  

System.InvalidOperationException: el objeto no se puede agregar a ObjectStateManager porque ya tiene una EntityKey. Use ObjectContext.Attach para adjuntar un objeto que tenga una clave existente.

Se crean nuevas entidades User y UserType. La EntityKey en UserType se ha configurado, pero cuando se la pasa a userEntities.Add () EF intenta establecer el estado AGREGADO. Como UserType tiene una EntityKey EF, se da cuenta de que algo está mal y lanza una excepción.

  

System.InvalidOperationException: un objeto con un valor EntityKey nulo no se puede adjuntar a un contexto de objeto.

En esta excepción, todo está bien con UserType, pero la excepción se genera porque la entidad Usuario no tiene EntityKey y, por lo tanto, no se puede adjuntar.

Así es como resolvería este problema (si, como usted dice, la codificación de referencias del diccionario de datos está bien):

En la entidad UserType, crearía referencias estáticas a los ID de UserType:

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

En la entidad Usuario, habría una propiedad extensora para un acceso más fácil a la clave externa 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, el caso de uso para crear un nuevo usuario se vería así:

using(UserEntities userEntities = new UserEntitites())
{
    User user = new User();
    user.UserTypeID = UserType.AdminUserTypeID;
    userEntities.AddToUser(user);
    userEntities.SaveChanges()
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top