Entity Framework: almacenar entidades sin guardar en la base de datos

¿Cómo almacenar un elemento temporal en ObjectContext sin guardar en la base de datos?

Almacenamiento de contexto en HttpContext, proporcionando por clase:

public static class HttpContextExtension
{
    public static MyEntityDataModelContainer GetMyContext(this HttpContext httpContext)
    {
        if (httpContext.Items["MyEntityDataModelContainer"] == null)
        {
            httpContext.Items.Add("MyEntityDataModelContainer", new MyEntityDataModelContainer());
        }

        return (MyEntityDataModelContainer)httpContext.Items["MyEntityDataModelContainer"];
    }
}

Hay dos páginas vacías: 1) FirstPage.aspx.cs:

public class FirstPage : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        // crete new item
        MyEntity newTemporaryItem = new MyEntity { MyEntityID = Guid.NewGuid() };
        // attach them to Context
        HttpContext.Current.GetMyContext().MyEntitySet.Attach(newTemporaryItem);
        // save changes
        HttpContext.Current.GetMyContext().SaveChanges();

        // get all attached to Context items
        var addedItems = (from se in HttpContext.Current.GetMyContext().ObjectStateManager.GetObjectStateEntries(EntityState.Unchanged)
                          where se.Entity is MyEntity
                          select se.Entity).AsQueryable();
        int CountInFirstPage = addedItems.Count();
    }
}

¿Entonces CountInFirstPage = 1.

2) SecondPage.aspx.cs:

public class FirstPage : Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        // get added in First page items From HttpContext
        var addedItems = (from se in HttpContext.Current.GetMyContext().ObjectStateManager.GetObjectStateEntries(EntityState.Unchanged)
                          where se.Entity is MyEntity
                          select se.Entity).AsQueryable();
        int CountInSecondPage = addedItems.Count();
    }
}

Aquí CountInSecondPage = 0.

¿Dónde me equivoco?

preguntado el 10 de mayo de 11 a las 13:05

3 Respuestas

¿Tengo razón en que la segunda página es una segunda solicitud?

En ese caso, tiene una nueva colección HttpContext.Items y sus valores de la última solicitud se han ido. Considere utilizar una sesión para almacenar estos valores en tal caso.

Nota al pie: EntityContext solo debe usarse para una solicitud y puede almacenarse en la colección HttpContext.Items por ese motivo, ¡pero nunca como un valor de sesión! Guarde solo los resultados aquí como el recuento.

contestado el 10 de mayo de 11 a las 18:05

Sí, segmentación de SecondPage desde FirstPage por enlace ... Intentando usar Sesión - asolovyov

¡Funciona! Rehice HttpContextExtension a través de httpContext.Session. ¡Gracias! - asolovyov

Eso no es nada nuevo y solo necesito citar a @BrokenGlass Pero incluso si fuera posible almacenar el contexto de la base de datos de esa manera, es decir, incluso si decidiera almacenarlo en la sesión, este no es el camino a seguir, el alcance de cada contexto debe ser una sola unidad de trabajo, no debe manténgalo activo durante un período de tiempo prolongado, especialmente en un entorno Web. Es realmente malo mantener vivo su EntityContext en un entorno web. Debería siempre déjalo y simplemente almacene los resultados que pueda necesitar más adelante. Hay tantas desventajas que nunca encajan en este comentario. - SRA

No pierde tanto rendimiento cuando configura el EntityContext nuevo con cada solicitud. Y en su ejemplo, solo necesitaba el recuento en la siguiente solicitud. También puede almacenar esos valores como parámetros GET en el enlace que lo liberó de una sesión. Con eso estarán disponibles en la próxima vista. En mi opinión, esa sería la solución más limpia para su caso. El valor es almacenar exactamente donde lo necesita. No importa si solo hay uno o cientos, SRA

Hay un libro realmente bueno sobre EntityFramework 4 de Julie Lerman Deberías leerlo. - SRA

Este es el enfoque equivocado HttpContext solo tiene el alcance de una única solicitud HTTP, por lo que se trata de un contexto diferente en la segunda solicitud.

Pero incluso si fuera posible almacenar el contexto de la base de datos de esa manera, es decir, incluso si decidiera almacenarlo en la sesión, este no es el camino a seguir, el alcance de cada contexto debe ser una sola unidad de trabajo, no debe manténgalo activo durante un período de tiempo prolongado, especialmente en un entorno Web.

Simplemente guarde sus elementos temporales en la sesión directamente y cree un nuevo contexto para cargar estos elementos cuando esté listo para hacerlo.

contestado el 10 de mayo de 11 a las 17:05

-1 La sesión es una mala solución para un objeto de Entity Framework. EF solo enumera según sea necesario, por lo que los objetos secundarios no van a existir y cuando llame al método de guardar cambios para EF, fallará. - Chad

Por lo que puedo decir desde arriba, la instancia de clase es solo una clase de entidad sin otras dependencias y no adjunta a un contexto, por lo que al igual que puede guardar cualquier otra instancia de clase en la sesión, debería poder hacer lo mismo con Éste. No entiendo bien tu preocupación. - Vidrio roto

Necesita recuperar el objeto cambiado en la consulta en la segunda página que asumiría para un enlace de datos a un control. - Chad

@Chad Sí, usaré ese valor para vincularlo a ComboBox en la segunda página. Una forma posible es pasar valores a través de la sesión entre páginas y adjuntar los valores recibidos al contexto, ¿verdad? - asolovyov

@BrokenGlass No veo nada malo en tu publicación. No sé qué quiere decir Chad. por lo tanto +1 - SRA

Para ejecutar una consulta en sus nuevos datos usando EF, deberá guardar. Puede hacer una lista y luego ejecutar la consulta contra la lista, pero eso requerirá que mantenga la lista en algún tipo de memoria estática (estado de sesión, estado de vista, caché), pero si la lista es grande, eso puede crear otros problemas.

Podrías hacer todo en un TRANSACCIÓN. Pasar la transacción hasta que se comprometa o retrocede. Los objetos de la entidad se guardan, pero cuando la transacción se revierte, los cambios se deshacen. Creo que la transacción persistirá a través de devoluciones de datos y redireccionamientos, pero deberá confirmarse o eliminarse para cuando se procese su página.

contestado el 10 de mayo de 11 a las 17:05

¿Quiso decir "Pasar la transacción" == pasarla entre páginas? Pensé que funciona solo con un EntityContext ... - asolovyov

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