Entity Framework: хранение объектов без сохранения в базе данных

#c# #asp.net #entity-framework #httpcontext

#c# #asp.net #entity-framework #httpcontext

Вопрос:

Как сохранить временный элемент в ObjectContext без сохранения в базе данных?

Сохранение контекста в HttpContext, предоставление по классу:

 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"];
    }
}
  

Есть две пустые страницы:
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();
    }
}
  

Итак, 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();
    }
}
  

Здесь CountInSecondPage = 0.

Где я ошибаюсь?

Ответ №1:

Прав ли я, что вторая страница — это второй запрос?

В этом случае у вас есть новый HttpContext.Коллекция элементов и ваши значения из последнего запроса исчезли. Рассмотрите возможность использования сеанса для хранения этих значений в таком случае.

Примечание: EntityContext следует использовать только для одного запроса и может быть сохранен в HttpContext.Элементы собираются по этой причине, но никогда в качестве значения сеанса! Сохраняйте здесь только результаты, такие как количество.

Комментарии:

1. Да, на вторую страницу осуществляется таргетинг с первой страницы по ссылке… Попытка использовать сеанс

2. Это работает! Я переделал HttpContextExtension через HttpContext.Session. Спасибо!

3. В этом нет ничего нового, и мне просто нужно процитировать @BrokenGlass Но даже если бы было возможно сохранить контекст БД таким образом, т. Е. Даже если вы решили сохранить его в сеансе — это неправильный путь — область действия каждого контекста должна составлять единую единицу работы, вы не должны поддерживать его в рабочем состоянии в течение длительного периода времени, особенно в веб-среде. Действительно плохо поддерживать ваш EntityContext в веб-среде. Вы должны всегда отбрасывать это и просто сохранять результаты, которые могут вам понадобиться позже. Существует так много недостатков, которые никогда не вписываются в этот комментарий.

4. Вы не теряете так много производительности при настройке EntityContext нового с каждым запросом. И в вашем примере вам просто нужно было подсчитать в следующем запросе. Вы также могли бы сохранить эти значения как параметры GET в ссылке, что освобождает вас от сеанса. При этом они будут доступны в следующем представлении. На мой взгляд, это было бы самым чистым решением для вашего случая. Значение — хранить именно там, где вам было нужно. Не имеет значения, есть ли только один или сотни

5. Есть действительно хорошая книга о EntityFramework 4 от Джули Лерман , вы должны прочитать ее.

Ответ №2:

Это неправильный подход, HttpContext имеет область действия только одного HTTP-запроса, поэтому во втором запросе вы имеете дело с другим контекстом.

Но даже если бы было возможно сохранить контекст БД таким образом, т. Е. Даже если вы решили сохранить его в сеансе — это неправильный путь — область действия каждого контекста должна быть отдельной единицей работы, вы не должны поддерживать его в рабочем состоянии в течение длительного периода времени, особенно в веб-среде.

Просто сохраните ваши временные элементы непосредственно в сеансе и создайте новый контекст для загрузки этих элементов, когда будете готовы.

Комментарии:

1. -1 Сессия является плохим решением для объекта Entity Framework. EF перечисляет только по мере необходимости, поэтому любые дочерние объекты не будут существовать, и когда вы вызываете метод save changes для EF, произойдет сбой.

2. Насколько я могу судить из приведенного выше, экземпляр класса — это просто класс сущностей, не имеющий других зависимостей и не привязанный к контексту, поэтому, точно так же, как вы можете сохранить любой другой экземпляр класса в сеансе, вы должны быть в состоянии сделать то же самое с этим. Я не совсем понимаю вашу озабоченность.

3. Ему нужно извлечь измененный объект в запросе на второй странице, я бы предположил, для привязки данных к элементу управления.

4. @Chad Да, я буду использовать это значение, чтобы привязать его к ComboBox на второй странице. Один из возможных способов — передавать значения через сеанс между страницами и прикреплять полученные значения к контексту, верно?

5. @BrokenGlass Я не вижу ничего плохого в вашем сообщении. Не знаю, что имеет в виду Чад. следовательно 1

Ответ №3:

Чтобы выполнить запрос к вашим новым данным с использованием EF, вам нужно будет сохранить. Вы могли бы создать список to, а затем выполнить запрос к списку, но для этого потребуется сохранить список в какой-либо статической памяти (состояние сеанса, состояние просмотра, кэш), но если список большой, это может создать другие проблемы.

Вы могли бы сделать все в ТРАНЗАКЦИИ. Передача транзакции по кругу до тех пор, пока вы либо не зафиксируете, либо не выполните откат. Объекты entity сохраняются, но когда транзакция откатывается, все изменения отменяются. Я думаю, что транзакция будет сохраняться с помощью обратных отправлений и перенаправлений, но ее необходимо будет зафиксировать или удалить к моменту отображения вашей страницы.

Комментарии:

1. Вы имели в виду «передачу транзакции по кругу» == передавать ее между страницами? Я думал, что это работает только с одним EntityContext…