Objeto existente de actualización de Entity Framework

He agregado una fila a mi base de datos y vuelvo con un contexto diferente para actualizarla. tengo esta clase:

public abstract partial class DataManager<I, C> 
    where C : class, IDomainObject, I, new( ) where I : IDomainObject

C podría ser un EntityObject, pero esta clase no lo sabe.

Mi guardado se ve así:

    public virtual bool Save( I _item )
    {
        bool rc = true;
        try
        {
        var set = m_Context.GetObjectSet<I, C>( );
        ObjectStateEntry stateEntry = null;
        if( ! m_Context.ObjectStateManager.TryGetObjectStateEntry( ( C ) _item, out stateEntry ) )
        {
            if( _item is EntityObject )
            {
                    if ( _item.IsNew )
                    {
                        set.AddObject( ( C ) _item );
                    }
                    else
                    {
                        try
                        {
                            set.Attach( ( C ) _item );
                        }
                        catch( Exception ex )
                        {
                            set.ApplyCurrentValues( ( C ) _item );
                        }

y así...

En mi caso de prueba, TryGetObjectStateEntry no encuentra stateEntry. Sin embargo, es un EntityObject, y no es nuevo (IsNew es mi indicador), por lo que llega al otro. Aquí está mi problema: set.Adjuntar arroja este error

"Ya existe un objeto con la misma clave en ObjectStateManager. ObjectStateManager no puede rastrear varios objetos con la misma clave".

y en el siguiente instante, ApplyCurrentValues ​​arroja este:

"No se pudo encontrar un objeto con una clave que coincida con la clave del objeto proporcionado en ObjectStateManager. Verifique que los valores de clave del objeto proporcionado coincidan con los valores de clave del objeto al que se deben aplicar los cambios".

¿Cómo pueden ambos ser verdad?

MÁS INFORMACIÓN:

_item fue creado por un Get en otro contexto. A continuación, se eliminó ese contexto. En ese momento, _item tenía un EntityState.Unchanged. Le apliqué algunos cambios y cambió a EntityState.Modified. (No esperaba eso, ya que el contexto (y su ObjectStateManager) deberían haber desaparecido). En cualquier caso, una vez que llega a Guardar (arriba), su estado (según lo informado por el depurador) es Modificado, pero tengo un nuevo contexto para entonces. Si obtengo una lista de TODOS los ObjectStateEntries (Agregados, Eliminados, Modificados, Sin cambios) en este punto, solo hay dos, y _item no es uno de ellos, como informa ApplyCurrentValues, pero no se puede adjuntar porque "es ¡también allí!". Quizás el problema es que todavía está conectado a un antiguo ObjectStateManager (¿podría haber alguna referencia que no permita que el ObjectStateManager se deshaga?).

preguntado el 29 de junio de 12 a las 20:06

¿Estás llamando a context.SaveChanges() dos veces? -

@DannyVarod: estoy usando UnitOfWork, en el que solo llamo a SaveChanges cuando me deshago de la Unidad y me deshago del Contexto al mismo tiempo. Esta es una aplicación web, por lo que tiene ciclos de vida muy cortos para Context. WcfService ha usado una UnitOfWork para obtener _item (ese "Obtener en otro contexto" que mencioné). Pero una vez que llegamos a Guardar, no hay oportunidad de que SaveChanges sea llamado dos veces. -

¿Y está seguro de que no está obteniendo el mismo Uow dos veces de su marco de inyección de dependencia? -

@DannyVarod - Estoy bastante seguro. Escribo el HashCode de contexto cada vez que instancia un Uow y cada vez que llamo a Guardar. Obtuve un número diferente para el contexto que cargó la fila del contexto que intenta guardarla... Pero, digamos que me falta algo. Tal vez esté en algo: ¿Cómo podría usar el mismo Uow o llamar a SaveChanges dos veces? ¿ApplyCurrentValues ​​y Attach no están de acuerdo sobre si un objeto está en ObjectStateManager o no? Tenga en cuenta que estos dos errores "diferentes" son consecutivos sin ningún código intermedio (mío). -

No he visto su código Uow, sin embargo, con EF puede llamar a SaveChanges() varias veces antes de llamar a AcceptChanges(). ¿Podría una de sus otras entidades guardadas tener una referencia al objeto guardado doble? -

2 Respuestas

El problema es que cada vez que se inicializa el contexto de base de datos, toma las filas de la base de datos y, para cada fila, asigna una clave de entidad. lo que significa que la misma fila, recuperada por 2 db-context tendrá 2 claves de entidad diferentes. la clave de entidad es como una identificación en el marco de la entidad y se usa en lugar de la identificación de la entidad en cuestión. Pero las restricciones de las tablas se conservan (sin clave principal duplicada) Espero que esto tenga sentido.

Respondido el 29 de junio de 12 a las 20:06

La respuesta tiene sentido, pero la pregunta es, ¿cómo puede Adjuntar el mismo objeto en el mismo contexto como "ya existe" y ApplyCurrentValues ​​como "no se pudo encontrar"? - kelly cline

Sinceramente, no sé qué está causando el segundo problema. pero intente resolver el primero y tal vez esté relacionado con el segundo. Sugiero (prueba rápida) que use un dbcontext estático - Boomer

El problema es que está adjuntando dos usuarios diferentes con la misma organización; sin embargo, el objeto de la organización es una instancia diferente en cada caso.

Si la organización ya está en la base de datos, intente:

  1. Establecer las propiedades de navegación para la organización en nulo y solo establecer las propiedades de OrganizationId.

  2. O cargue la entidad de la organización desde la base de datos y colóquela en los accesorios de navegación.

Si la organización no está en la BD:

Use la misma instancia (deseche uno y reemplácelo con el otro).

Respondido 02 Jul 12, 21:07

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.