Domanda

Nel mio modello di dati ho una divisione abbastanza comune tra i miei oggetti / tabelle / dati:

  • " transazionale " entità che rappresentano il lavoro svolto dal sistema. Queste entità sono create dal sistema e sono importanti solo in contesti specifici. Sono regolarmente creati al volo. (A parte: esiste un nome proprio per questo tipo di entità?)
  • " Dizionario dati " entità che rappresentano proprietà comuni delle entità transazionali. Questi sono definiti in modo irregolare (principalmente all'inizio del progetto) e hanno un ciclo di vita molto più statico. Sono in genere creati da me.

Quindi, ad esempio, potrei avere un'entità utente (transazionale) e un'entità UserType (dizionario dati).

Voglio inserire nel mio codice riferimenti (concreti) alle istanze delle entità del Dizionario dei dati. Questo mi dà la possibilità di codificare la logica aziendale con un linguaggio di facile comprensione. (Quindi, ad esempio, potrei avere un UserType di "Plain" e un UserType di "Admin", e quindi una regola che dice "consentire l'accesso solo se UserType dell'Utente è uguale a Admin").

Uso LINQ-to-Entities come tecnologia di accesso ai dati / ORM. Per implementare i riferimenti del dizionario dei dati, sto memorizzando EntityKeys. La mia comprensione è che sono distaccati dal contesto dell'oggetto e quindi sono adatti a questo scopo. (Dato che non contengono lo stato dell'entità, anche io non devo preoccuparmi che lo stato diventi stantio.)

Tuttavia, ciò mi dà problemi quando provo ad aggiungere una nuova entità transazionale con un riferimento DD-EntityKey. Continuando il mio esempio, sto facendo questo:

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

... e questo mi dà il seguente errore:

  

System.InvalidOperationException: l'oggetto non può essere aggiunto a ObjectStateManager perché ha già un EntityKey. Utilizzare ObjectContext.Attach per collegare un oggetto che ha una chiave esistente.

Se provo a chiamare userEntities.Attach (utente) invece di AddToUser, ottengo questo:

  

System.InvalidOperationException: un oggetto con un valore EntityKey null non può essere collegato a un contesto di oggetto.

Entrambi questi errori hanno senso, data la mescolanza di entità nuove e preesistenti che sto facendo. Ciò di cui non sono sicuro è come aggirare questo problema. Esiste un modo in cui posso avere riferimenti distinti alle entità DD e assegnarli a nuovi oggetti collegati senza richiedere che io carichi l'intero stato dell'entità DD?

È stato utile?

Soluzione

Proverò a spiegare perché stai ricevendo queste eccezioni:

  

System.InvalidOperationException: l'oggetto non può essere aggiunto a ObjectStateManager perché ha già un EntityKey. Utilizzare ObjectContext.Attach per collegare un oggetto che ha una chiave esistente.

Vengono create nuove entità User e UserType. EntityKey su UserType è stato impostato ma quando lo si passa a userEntities.Add () EF tenta di impostare lo stato ADDED. Poiché UserType ha un EntityKey EF si rende conto che qualcosa non va e genera un'eccezione.

  

System.InvalidOperationException: un oggetto con un valore EntityKey null non può essere collegato a un contesto di oggetto.

In questa eccezione tutto va bene con UserType, ma l'eccezione viene generata perché Entità utente: non ha EntityKey e quindi non può essere collegato.

Ecco come risolverei questo problema (se, come dici tu, la codifica dei riferimenti del dizionario dei dati è ok):

Sull'entità UserType vorrei creare riferimenti statici agli ID UserType:

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

Sull'entità utente ci sarebbe la proprietà extender per un più facile accesso alla chiave esterna 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;
        }
    }
}

Infine, il caso d'uso per creare un nuovo utente sarebbe simile al seguente:

using(UserEntities userEntities = new UserEntitites())
{
    User user = new User();
    user.UserTypeID = UserType.AdminUserTypeID;
    userEntities.AddToUser(user);
    userEntities.SaveChanges()
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top