Удаление ObjectContext в EF репозитории ASP.NET Приложение MVC 3

#c# #asp.net-mvc #entity-framework #repository

#c# #asp.net-mvc #entity-framework #репозиторий

Вопрос:

итак, я получаю The ObjectContext instance has been disposed and can no longer be used for operations that require a connection. ошибку при попытке получить доступ к ObjectContext через репозиторий в OnActionExecuting ActionFilterAttribute .

My ActionFilterAttribute проверяет наличие HTTP-cookie. Если он существует, он проверяет его в базе данных, обновляет срок его действия, а затем добавляет его в Controller ViewData коллекцию, чтобы к нему могли получить доступ ActionResult ‘ы. Если он не существует, то он перенаправляет пользователя на страницу входа в систему.

Фильтр работает наполовину, потому что, когда HTTP cookie существует и он пытается извлечь конкретный объект из базы данных, происходит сбой с приведенным выше сообщением об ошибке.

Из-за большого количества слоев, которые уже установлены, я собираюсь опубликовать код для всех из них, VerifyCookieAttribute.cs , CookieRepository.cs и Repository_1.cs . Наконец, хотя это, вероятно, не имеет никакого значения, ошибка возникает в SelectSingle методе Repository_1.cs .

Внедрение зависимостей выполняется Ninject 2.2.1.0. Отложенная загрузка в настоящее время включена, но любая настройка выдает ту же ошибку.

В любом случае, я был бы признателен за некоторые указания относительно того, где я ошибаюсь во всем этом. Заранее спасибо за любую помощь!

 //  VerifyCookieAttribute.cs
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
internal class VerifyCookieAttribute : ActionFilterAttribute {
    [Inject]
    public CookieRepository Repository { private get; set; }

    private HttpRequestBase Request = null;
    private HttpResponseBase Response = null;

    private readonly bool Administration = false;
    private readonly bool Customers = false;

    private readonly string[] ExcludedPaths = new string[2] {
        "/Administration",
        "/Customers"
    };

    public VerifyCookieAttribute(
        bool Administration,
                    bool Customers) {
    this.Administration = Administration;
    this.Customers = Customers;
}

    public override void OnActionExecuting(
        ActionExecutingContext ActionExecutingContext) {
        this.Request = ActionExecutingContext.HttpContext.Request;

        if (!this.ExcludedPaths.Contains(this.Request.Url.AbsolutePath)) {
            this.Response = ActionExecutingContext.HttpContext.Response;

            if (this.Exists()) {
                Cookie Cookie = this.Get();

                this.Refresh(Cookie);

                ActionExecutingContext.Controller.ViewData.Add("Cookie", Cookie);

                if (this.Administration) {
                    ActionExecutingContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new {
                        area = "Administration",
                        controller = "Administration",
                        action = "Dashboard"
                    }));
                } else if (this.Customers) {
                    //  Do Nothing
                };
            } else if (!this.Exists() amp;amp; !this.Response.IsRequestBeingRedirected) {
                if (this.Administration) {
                    ActionExecutingContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new {
                        area = "Administration",
                        controller = "Administration",
                        action = "Default"
                    }));
                } else if (this.Customers) {
                    ActionExecutingContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new {
                        area = "Customers",
                        controller = "Customers",
                        action = "Default"
                    }));
                };
            };
        };
    }

    private bool Exists() {
        string Token = this.GetHttpCookieToken();

        return (!String.IsNullOrEmpty(Token) amp;amp; (Token.Length == 256));
    }

    private Cookie Get() {
        string Token = this.GetHttpCookieToken();

        Cookie Cookie = this.Repository.SelectSingle(
            c =>
                (c.Token == Token));

        return (Cookie);
    }

    private string GetHttpCookieToken() {
        if (this.Request.Cookies["NWP"] != null) {
            return this.Request.Cookies["NWP"]["Token"];
        };

        return (string.Empty);
    }

    private void Refresh(
        Cookie Cookie) {
        if (Cookie.RefreshStamp <= DateTime.Now.AddHours(1)) {
            this.Repository.RefreshCookie(Cookie.CookieId);

            this.SetHttpCookie(Cookie);
        };
    }

    private void SetHttpCookie(
        Cookie Cookie) {
        this.Response.Cookies["NWP"]["Token"] = Cookie.Token;
        this.Response.Cookies["NWP"].Expires = Cookie.RefreshStamp.AddHours(1);
    }
}

//   CookieRepository.cs
public sealed class CookieRepository : Repository<Cookie> {
    [Inject]
    public CookieRepository(
        Entities Entities)
        : base(Entities, true) {
    }

    public void RefreshCookie(
        int CookieId) {
        this.Entities.ExecuteFunction("RefreshCookie", new ObjectParameter("CookieId", CookieId));
    }
}

//  Repository`1.cs
public class Repository<TEntity> : IRepository<TEntity> where TEntity : class {
    protected readonly Entities Entities = null;

    private readonly IObjectSet<TEntity> EntitySet = null;

    [Inject]
    public Repository(
        Entities Entities)
        : this(Entities, true) {
    }

    [Inject]
    public Repository(
        Entities Entities,
        bool CreateEntitySet) {
        this.Entities = Entities;

        if (CreateEntitySet) {
            this.EntitySet = this.Entities.CreateObjectSet<TEntity>();
        };
    }

    public virtual void Delete(
        TEntity TEntity) {
        this.EntitySet.DeleteObject(TEntity);
    }

    public virtual void Insert(
        TEntity TEntity) {
        this.EntitySet.AddObject(TEntity);
    }

    public virtual IQueryable<TEntity> Select() {
        return this.EntitySet;
    }

    public virtual IQueryable<TEntity> Select(
        Expression<Func<TEntity, bool>> Selector) {
        return this.EntitySet.Where(Selector);
    }

    public virtual bool SelectAny(
        Expression<Func<TEntity, bool>> Selector) {
        return this.EntitySet.Any(Selector);
    }

    public virtual IList<TEntity> SelectList() {
        return this.EntitySet.ToList();
    }

    public virtual IList<TEntity> SelectList(
        Expression<Func<TEntity, bool>> Selector) {
        return this.EntitySet.Where(Selector).ToList();
    }

    private IList<TEntity> SelectOrderedList(
        bool Ascending,
        params Expression<Func<TEntity, IComparable>>[] Orderers) {
        IOrderedQueryable<TEntity> Queryable = null;

        foreach (Expression<Func<TEntity, IComparable>> Orderer in Orderers) {
            if (Queryable == null) {
                Queryable = (Ascending ? this.EntitySet.OrderBy(Orderer) : this.EntitySet.OrderByDescending(Orderer));
            } else {
                Queryable = (Ascending ? Queryable.ThenBy(Orderer) : Queryable.ThenByDescending(Orderer));
            };
        };

        return (Queryable.ToList());
    }

    public virtual IList<TEntity> SelectOrderedList(
        params Expression<Func<TEntity, IComparable>>[] Orderers) {
        return this.SelectOrderedList(true, Orderers);
    }

    public virtual IList<TEntity> SelectOrderedDescendingList(
        params Expression<Func<TEntity, IComparable>>[] Orderers) {
        return this.SelectOrderedList(false, Orderers);
    }

    public virtual TEntity SelectSingle(
        Expression<Func<TEntity, bool>> Selector) {
        return this.EntitySet.Single(Selector);
    }

    public virtual void Update() {
        this.Entities.SaveChanges();
    }

    public virtual IEnumerable<TEntity> Where(
        Expression<Func<TEntity, bool>> Selector) {
        return this.EntitySet.Where(Selector);
    }
}
  

Обновить

Вот трассировка стека по запросу @jfar:


System.Data.Objects.ObjectContext.EnsureConnection() 8550458
System.Data.Objects.ObjectQuery 1.GetResults(Nullable 1 forMergeOption) 46
System.Data.Objects.ObjectQuery 1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() 44
System.Linq.Enumerable.Single(IEnumerable
1 source) 184
System.Data.Objects.ELinq.ObjectQueryProvider.b_3(IEnumerable 1 sequence) 41
System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle(IEnumerable
1 query, Expression queryRoot) 59
System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute(Expression expression) 150
System.Linq.Queryable.Single(IQueryable 1 source, Expression 1 predicate) 300
{WITHHELD}.Repositories.Repository 1.SelectSingle(Expression 1 Selector) in C:Projects{WITHHELD}{WITHHELD}RepositoriesRepository 1.cs:98
VerifyCookieAttribute.Get() in C:Projects{WITHHELD}{WITHHELD}AttributesVerifyCookieAttribute.cs:100
VerifyCookieAttribute.OnActionExecuting(ActionExecutingContext ActionExecutingContext) in C:Projects{WITHHELD}{WITHHELD}AttributesVerifyCookieAttribute.cs:55
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func
1 continuation) 47
System.Web.Mvc.<>c
_DisplayClass17.b_14() 19
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func 1 continuation) 263
System.Web.Mvc.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14() 19
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func
1 continuation) 263
System.Web.Mvc.<>c
_DisplayClass17.b_14() 19
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func 1 continuation) 263
System.Web.Mvc.<>c__DisplayClass17.<InvokeActionMethodWithFilters>b__14() 19
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList
1 filters, ActionDescriptor actionDescriptor, IDictionary 2 parameters) 191
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) 343
System.Web.Mvc.Controller.ExecuteCore() 116
System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext) 97
System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext) 10
System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__5() 37
System.Web.Mvc.Async.<>c__DisplayClass1.<MakeVoidDelegate>b__0() 21
System.Web.Mvc.Async.<>c__DisplayClass8
1.b
_7(IAsyncResult ) 12
System.Web.Mvc.Async.WrappedAsyncResult`1.End() 62
System.Web.Mvc.<>c
_DisplayClasse.b_d() 50
System.Web.Mvc.SecurityUtil.b
_0(Action f) 7
System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) 22
System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) 60
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) 9
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() 8862381
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Booleanamp; completedSynchronously) 184

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

1. Можете ли вы опубликовать трассировку стека, где генерируется исключение? Звучит как проблема с отложенной загрузкой, но для просмотра потребуется стек.

2. @jfar, я обновил сообщение трассировкой стека. Я не знаю, как правильно отформатировать его для SO, поэтому я сделал то, что мог…

Ответ №1:

Я предполагаю, что вы используете mvc 3.

В предыдущих версиях ASP.NET MVC, фильтры действий создаются для каждого запроса, за исключением нескольких случаев. Это поведение никогда не было гарантированным поведением, а просто деталью реализации, и контракт для фильтров заключался в том, чтобы считать их не имеющими состояния. В ASP.NET В MVC 3 фильтры кэшируются более агрессивно. Следовательно, могут быть нарушены любые пользовательские фильтры действий, которые ненадлежащим образом сохраняют состояние экземпляра.

Это означает, что атрибуты не создаются для каждого запроса, поэтому любая InRequestScope инъекция не будет работать. Вам нужно будет либо внедрить IServiceProvider и получать ваш репозиторий с этим при каждом запросе, либо создать новый контекст вручную.

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

1. Спасибо @Lukas! Я действительно помню, что читал это некоторое время назад, но я никогда не удосуживался усвоить это, поскольку в то время я не использовал DI…