Question

Dans mon modèle de données, j'ai une division assez commune entre mes objets / tables / données:

  • " Transactionnel " entités qui représentent le travail effectué par le système. Ces entités sont créées par le système et ne sont importantes que dans des contextes spécifiques. Ils sont régulièrement créés à la volée. (A part: y a-t-il un nom propre pour ce type d'entité?)
  • " Dictionnaire de données " entités qui représentent les propriétés communes des entités transactionnelles. Celles-ci sont définies de manière irrégulière (principalement au début du projet) et ont un cycle de vie beaucoup plus statique. Ils sont généralement créés par moi.

Ainsi, par exemple, je pourrais avoir une entité utilisateur (transactionnelle) et une entité de type utilisateur (dictionnaire de données).

Je souhaite coder (en dur) les références aux instances des entités de dictionnaire de données dans mon code. Cela me donne la possibilité de coder la logique métier avec un langage facile à comprendre. (Ainsi, par exemple, je pourrais avoir un UserType de "Plain" et un UserType de "Admin", puis une règle qui dit "autorise l'accès uniquement si UserType de l'utilisateur est égal à Admin").

J'utilise LINQ-to-Entities comme technologie d'accès aux données / ORM. Pour implémenter les références du dictionnaire de données, je stocke EntityKeys. D'après ce que je comprends, ils sont détachés du contexte de l'objet et conviennent donc à cette fin. (Comme ils ne contiennent pas d'état d'entité, je n'ai pas non plus à craindre que cet état devienne obsolète.)

Cependant, cela me pose des problèmes lorsque j'essaie d'ajouter une nouvelle entité transactionnelle avec une référence DD-EntityKey. En continuant mon exemple, je fais ceci:

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

... et cela me donne l'erreur suivante:

  

System.InvalidOperationException: L'objet ne peut pas être ajouté à ObjectStateManager car il possède déjà une EntityKey. Utilisez ObjectContext.Attach pour attacher un objet ayant une clé existante.

Si j'essaie d'appeler userEntities.Attach (utilisateur) au lieu de AddToUser, j'obtiens ceci:

  

System.InvalidOperationException: un objet avec une valeur EntityKey null ne peut pas être associé à un contexte d'objet.

Ces deux erreurs ont du sens, étant donné le mélange d’entités nouvelles et préexistantes que je suis en train de créer. Ce que je ne sais pas, c'est comment résoudre ce problème. Existe-t-il un moyen de détacher des références à des entités DD et de les affecter à de nouveaux objets attachés sans me demander de charger tout l'état de cette entité?

Était-ce utile?

La solution

Je vais essayer d'expliquer pourquoi vous obtenez ces exceptions:

  

System.InvalidOperationException: L'objet ne peut pas être ajouté à ObjectStateManager car il possède déjà une EntityKey. Utilisez ObjectContext.Attach pour attacher un objet ayant une clé existante.

De nouvelles entités User et UserType sont créées. La EntityKey sur UserType a été définie, mais lorsque vous la transmettez à userEntities.Add () EF tente de leur attribuer l'état ADDED. Depuis que UserType a un EntityKey, EF réalise que quelque chose ne va pas et lève une exception.

  

System.InvalidOperationException: un objet avec une valeur EntityKey null ne peut pas être associé à un contexte d'objet.

Dans cette exception, tout est ok avec UserType, mais l'exception est levée parce que l'entité User - elle n'a pas de clé EntityKey et ne peut donc pas être attachée.

Voici comment résoudre ce problème (si, comme vous le dites, le codage en dur des références de dictionnaire de données est correct):

Sur l'entité UserType, je créerais des références statiques aux identifiants UserType:

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

Sur l'entité utilisateur, il y aurait une propriété d'extendeur pour un accès plus facile à la clé étrangère 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;
        }
    }
}

Enfin, le cas d'utilisation de la création d'un nouvel utilisateur ressemblerait à ceci:

using(UserEntities userEntities = new UserEntitites())
{
    User user = new User();
    user.UserTypeID = UserType.AdminUserTypeID;
    userEntities.AddToUser(user);
    userEntities.SaveChanges()
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top