Почему мой DataContext нулевой только в одном действии? - PullRequest
1 голос
/ 10 июня 2009

У меня в BaseController есть свойство DataContext, которое содержит мой контекст данных LINQ to SQL (или поддельный контекст для тестирования). При использовании конструктора без параметров (другими словами, при выполнении запроса к ASP.NET MVC) этому свойству присваивается новый экземпляр моего контекста данных LINQ to SQL:

public class BaseController : Controller {
    public IDataContextWrapper DataContext { get; set; }

    public BaseController() : this(new DataContextWrapper<MyDataContext>()) { }

    public BaseController(IDataContextWrapper context) {
        DataContext = context;
    }
}

Также в моем BaseController я установил некоторые глобальные элементы ViewData:

protected override void OnActionExecuting(ActionExecutingContext filterContext) {
    ViewData["Example"] = DataContext.Table<Example>().Count();
    base.OnActionExecuting(filterContext);
}

Это нормально работает практически для каждого действия. Единственное, что не работает, это действие Logout на моем AccountController:

public ActionResult Logout() {
    FormsAuth.SignOut();
    return RedirectToResult("Login");
}

Это вызывает исключение NullReferenceException во время BaseController.OnActionExecuting. При выполнении этого конкретного действия свойство DataContext имеет значение null.

Почему это происходит только в одном действии?

Примечание: IDataContextWrapper и DataContextWrapper просто обертывают существующую функциональность объекта LINQ to SQL DataContext, чтобы его можно было заменить поддельным контекстом в модульных тестах. Он не выполняет никаких действий самостоятельно, но оставляет его на усмотрение базового DataContext, так что я уверен, что это не проблема.

Ответы [ 2 ]

1 голос
/ 10 июня 2009

Чтобы прокомментировать мой комментарий, проверьте эту ссылку и, более конкретно, ссылку на документацию Microsoft здесь , в которой указано:

Как правило, экземпляр DataContext рассчитан на одну «единицу работы», однако ваше приложение определяет этот термин. DataContext легок и не дорог в создании. Типичное приложение LINQ to SQL создает экземпляры DataContext в области действия метода или как член недолговечных классов, представляющих логический набор связанных операций с базой данных.

Microsoft проделала ужасную работу, объясняя это и откровенно объясняя, в первую очередь, использование Linq в многоуровневой среде. В моем конкретном случае у меня был один (статический) текст данных, реализованный с помощью шаблона Singleton, который, как я полагаю, и вы сделали. (Так как это самый логичный дизайн, ИМХО). Это, однако, крайне НЕ способ делать вещи. В моем случае исправление было довольно простым, меняя мой вызов GetDataContext (), чтобы каждый раз возвращать новый DataContext, вместо того, чтобы возвращать статический экземпляр. Это, однако, вы обнаружите, создает целый ряд новых проблем. Никто из них не станет непреодолимым, когда вы их поймете, но определенно боль.

Если у вас есть такая настройка (средства доступа Singleton для вашего DataContext), измените ее, чтобы посмотреть, решит ли она вашу проблему.

В любом случае, не используйте глобальный DataContext и не сохраняйте DataContext, если имеете дело с n-уровневой архитектурой.

Даже если это не решит вашу конкретную проблему, я настоятельно рекомендую вам перестроить свое решение, чтобы у DataContexts была единица времени жизни, если оно вас уже не укусило, то оно будет.

0 голосов
/ 10 июня 2009

По причинам, которые я не совсем понимаю, когда создается новый AccountController для действия Logout, ASP.NET MVC использует второй конструктор с нулевым параметром (может быть ошибка?) Я изменил класс, чтобы создать новый DataContext по умолчанию, когда параметр имеет значение null:

public class BaseController : Controller {
    public IDataContextWrapper DataContext { get; set; }

    public BaseController() : this(null) { }

    public BaseController(IDataContextWrapper context) {
        DataContext = dataContext ?? new DataContextWrapper<MyDataContext>();
    }
}

Теперь это работает.

Мне кажется странным, что ASP.NET MVC в некоторых случаях использовал конструктор по умолчанию, а в других - перегрузку. Кто-нибудь может пролить свет на это?

...