Нет ничего необычного в создании одного ObjectContext
для каждого веб-запроса. Я делаю это в своих веб-приложениях. Тем не менее, ИМО, страница должна ничего не знать о ObjectContext
.
Поскольку вы уже говорите о внедрении контекста в конструктор службы, взгляните на внедрение зависимостей (если вы его еще не используете). Когда вы используете контейнер внедрения зависимостей, вы можете позволить контейнеру создать этот сервис для вас и внедрить контекст объекта в этот контейнер. Единственное, что ваша страница должна сделать, это запросить этот сервис из контейнера (в идеале, вы бы даже позволили этому сервису внедриться в конструктор этой страницы, но это невозможно с веб-формами).
Ваша страница будет выглядеть так:
public class MyPage : Page
{
private readonly IMyService service;
public MyPage()
{
this.service = Global.GetInstance<IMyService>();
}
protected void Btn1_OnClick(object s, EventArgs e)
{
this.service.DoYourThing(this.TextBox1.Text);
}
}
В пути запуска (Global.asax) вашего приложения вы можете настроить структуру внедрения зависимостей следующим образом:
private static Container Container;
public static T GetInstance<T>() where T : class
{
return container.GetInstance<T>();
}
void Application_Start(object sender, EventArgs e)
{
var container = new Container();
string connectionString = ConfigurationManager
.ConnectionStrings["MyCon"].ConnectionString;
// Allow the container to resolve your context and
// tell it to create a single instance per request.
container.RegisterPerWebRequest<MyContext>(() =>
new MyContext(connectionString));
// Tell the container to return a new instance of
// MyRealService every time a IMyService is requested.
// When MyContext is a constructor argument, it will
// be injected into MyRealService.
container.Register<IMyService, MyRealService>();
Container = container;
}
В этих примерах я использовал контейнер внедрения зависимостей Simple Injector , хотя подойдет любой контейнер DI. RegisterPerWebRequest
не является частью базовой библиотеки, но доступен в виде (NuGet) пакета расширения . Пакет гарантирует, что ваш ObjectContext
будет удален после завершения веб-запроса.
Поначалу это может показаться сложным, но при этом веб-странице вообще не нужно беспокоиться о деталях создания и утилизации ObjectContext
.
Далее, поместите логику, которая выполняет сценарий использования, в один класс: команду. Пусть команда (или система) обеспечивает атомарность этой операции. Не позволяйте странице отвечать за это и не фиксируйте в конце запроса, потому что в этот момент вы не будете знать, нормально ли будет вызывать commit. Нет, пусть команда справится с этим сама. Вот статья о написании бизнес-команд .
Этот совет относится и к ASP.NET MVC, хотя вы не должны вызывать Global.GetInstance<IMyService>()
внутри конструктора контроллера, а просто использовать внедрение конструктора (поскольку MVC имеет большую поддержку для этого) и использовать пакет интеграции MVC3 .
Также взгляните на этот вопрос Stackoverflow , в котором говорится о выборе между IObjectContextFactory
или ObjectContext
на запрос.