#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…