Entity Framework ASP. NET MVC (иногда) проблемы с DbContext.Set и в других местах. - PullRequest
1 голос
/ 20 февраля 2020

У меня странная проблема с использованием ASP. NET в сочетании с Entity Framework и Unity Container.

Эта проблема only возникает после запуска приложения от нескольких часов до нескольких дней. И после этого происходит временное исправление (снова на тот же период) путем перезапуска IIS.

Иногда проблема дает исключение при попытке ввести (используя unity-container) Контроллер.

Пример:

public class PersonController
{
     private readonly ICrudService<Person> personCrudservice;

     public PersonController(ICrudService<Person> personCrudservice) 
     {
         this.personCrudservice = personCrudservice;
     }
}

Исключением здесь является: An error occurred when trying to create a controller of type 'PersonController'. Make sure that the controller has a parameterless public constructor.

Конечно, контроллер не имеет конструктора без параметров, но использует контейнер-единство personCrudservice вводится Однако этого не происходит, поскольку метод dbContext.Set<Person>() дает следующее исключение: An item with the same key has already been added., что приводит к исключению, показанному выше.

Другим примером является исключение при попытке загрузить данные из базы данных. Что дает исключение NullReference. (Опять же, не все время и данные существуют в базе данных)

Можете ли вы, ребята, помочь мне решить проблему?

DataContext.cs :

public class DataContext : IUnitOfWork, IRepositoryFactory, ICrudServiceFactory
{
    private const string CONNECTIONSTRING = "Constring";
    private static readonly MedicijnverstrekkingDbContext dbContext = new MedicijnverstrekkingDbContext(CONNECTIONSTRING);
    public DbContext DbContext => dbContext;

    public static volatile Dictionary<string, object> repositories = new Dictionary<string, object>();

    public DataContext()
    {
        dbContext.Configuration.EnsureTransactionsForFunctionsAndCommands = false;
    }   

    public void SaveChanges()
    {
        dbContext.SaveChanges();
    }

    public void Dispose()
    {
        dbContext.Dispose();
    }

    public IRepository<T> CreateRepositoryFor<T>() where T : class, IEntity
    {
        var naam = typeof(T).FullName;
        var repos = default(IRepository<T>);

        if(repositories.ContainsKey(naam))
        {
            repos = repositories[naam] as IRepository<T>;
        }
        if(repos == null)
        {
            repos = new Repository<T>(dbContext.Set<T>());

            repositories[naam] = repos;
        }
        return repos;
    }

    ICrudService<T> ICrudServiceFactory.GenerateCrudServiceFor<T>(IUnityContainer unityContainer)
    {
        var icrudServiceType = typeof(ICrudService<T>);

        var tService = icrudServiceType.Assembly.GetTypes().Where(t => icrudServiceType.IsAssignableFrom(t)).FirstOrDefault();

        //If predefined crud service exists, create an instance, otherwise create a generic crud service.
        if (tService != null)
        {
            return (ICrudService<T>)Activator.CreateInstance(tService, new object[] { unityContainer.Resolve<IUnitOfWork>(), unityContainer.Resolve<IRepository<T>>() });
        }
        else
        {
            return new GenericCrudService<T>(unityContainer.Resolve<IUnitOfWork>(), unityContainer.Resolve<IRepository<T>>());
        }
    }
}

UnityConfig.cs

public class UnityConfig
{
    private static readonly Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
    {
        var container = new UnityContainer();
        RegisterTypes(container);
        return container;
    });

    public static IUnityContainer Container => container.Value;

    public static void RegisterTypes(IUnityContainer container)
    {
        RegisterDependencies(container);

        System.Web.Mvc.DependencyResolver.SetResolver(new UnityDependencyResolverAdapter(container));
        GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
    }

    private static void RegisterDependencies(IUnityContainer unityContainer)
    {
        RegisterDataContextAndUnitOfWork(unityContainer);
        RegisterRepositories(unityContainer);
        RegisterAuthenticationDependencies(unityContainer);
    }

    private static void RegisterDataContextAndUnitOfWork(IUnityContainer container)
    {
        container.RegisterType<IUnitOfWork, DataContext>(HttpContextLifetimeManager.FromType<DataContext>());
        container.RegisterType<IRepositoryFactory, DataContext>(HttpContextLifetimeManager.FromType<DataContext>());
        container.RegisterType<ICrudServiceFactory, DataContext>(HttpContextLifetimeManager.FromType<DataContext>());

    }

    private static void RegisterAuthenticationDependencies(IUnityContainer container)
    {
        container.RegisterType<IUserStore<GebruikerModel>, UserStore>(HttpContextLifetimeManager.FromType<UserStore>());
        container.RegisterType<IRoleStore<RoleModel, string>, RoleStore>(HttpContextLifetimeManager.FromType<RoleStore>());

        container.RegisterFactory<UserManager<GebruikerModel>>(unityContainer =>
        {
            var userStore = unityContainer.Resolve<IUserStore<GebruikerModel>>();
            var manager = new UserManager<GebruikerModel>(userStore)
            {
                PasswordHasher = new BcryptPasswordHasher()
            };
            manager.RegisterTwoFactorProvider("PhoneCode", new PhoneNumberTokenProvider<GebruikerModel>
            {
                MessageFormat = "Uw inlogcode is {0}."
            });
            manager.SmsService = new SmsService();
            return manager;
        });

        container.RegisterType<ICurrentUserProvider, CurrentHttpUserProvider>();
    }

    private static void RegisterRepositories(IUnityContainer container)
    {
        var registerRepositoryMethodName = MemberNameHelper.GetActionName(() => RegisterRepository<IEntity>(container));
        var registerCrudserviceName = MemberNameHelper.GetActionName(() => RegisterCrudService<IEntity>(container));
        var registerRepositoryMethodInfo = typeof(UnityConfig).GetMethod(registerRepositoryMethodName, BindingFlags.NonPublic | BindingFlags.Static);
        var registerCrudserviceMethodInfo = typeof(UnityConfig).GetMethod(registerCrudserviceName, BindingFlags.NonPublic | BindingFlags.Static);

        foreach (var entityType in typeof(IEntity).Assembly.GetTypes().Where(t => typeof(IEntity).IsAssignableFrom(t)))
        {
            var registerRepositoryMethod = registerRepositoryMethodInfo.MakeGenericMethod(entityType);
            registerRepositoryMethod.Invoke(null, new object[] { container });

            var registerCrudserviceMethod = registerCrudserviceMethodInfo.MakeGenericMethod(entityType);
            registerCrudserviceMethod.Invoke(null, new object[] { container });
        }
    }

    private static void RegisterRepository<T>(IUnityContainer unityContainer) where T : class, IEntity
    {
        unityContainer.RegisterFactory<IRepository<T>>(
            factory => factory.Resolve<IRepositoryFactory>().CreateRepositoryFor<T>(),
            HttpContextFactoryLifetimeManager.ForRepository<T>()
        );
    }


    private static void RegisterCrudService<T>(IUnityContainer unityContainer) where T : class, IEntity
    {
        unityContainer.RegisterFactory<ICrudService<T>>(
            factory => factory.Resolve<ICrudServiceFactory>().GenerateCrudServiceFor<T>(factory),
            HttpContextFactoryLifetimeManager.ForCrudService<T>()
            );
    }
}

У меня есть эта проблема уже несколько недель, и я пробовал разные LifeTimeManager, а также понижал Unity-Container / Entity Framework Помогите.

Stacktrace: элемент с таким же ключом уже добавлен.

   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at System.Data.Entity.Internal.InternalContext.Set[TEntity]()
   at System.Data.Entity.DbContext.Set[TEntity]()
   at Multitask.COMPANYNAME.DataAccess.EntityFramework.DataContext.CreateRepositoryFor[T]() in C:\Source\Workspaces\Multitask.COMPANYNAME\Multitask.COMPANYNAME\DataAccess\DataContext.cs:line 50
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Multitask.COMPANYNAME.WebApplication.Unity.HttpContextFactoryLifetimeManager.GetValue(ILifetimeContainer container) in C:\Source\Workspaces\Multitask.COMPANYNAME\Multitask.COMPANYNAME\WebApplication\Unity\HttpContextFactoryLifetimeManager.cs:line 60
   at Unity.Strategies.LifetimeStrategy.PreBuildUp(BuilderContext& context)
   at Unity.UnityContainer.<>c.<.ctor>b__73_1(BuilderContext& context)
   at Unity.UnityContainer.Unity.IUnityContainer.Resolve(Type type, String name, ResolverOverride[] overrides)
   at Unity.UnityContainerExtensions.Resolve[T](IUnityContainer container, ResolverOverride[] overrides)
   at Multitask.COMPANYNAME.DataAccess.EntityFramework.DataContext.Multitask.COMPANYNAME.Service.DataAccess.ICrudServiceFactory.GenerateCrudServiceFor[T](IUnityContainer unityContainer) in C:\Source\Workspaces\Multitask.COMPANYNAME\Multitask.COMPANYNAME\DataAccess\DataContext.cs:line 131
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Multitask.COMPANYNAME.WebApplication.Unity.HttpContextFactoryLifetimeManager.GetValue(ILifetimeContainer container) in C:\Source\Workspaces\Multitask.COMPANYNAME\Multitask.COMPANYNAME\WebApplication\Unity\HttpContextFactoryLifetimeManager.cs:line 70
   at Unity.Strategies.LifetimeStrategy.PreBuildUp(BuilderContext& context)
   at Unity.UnityContainer.<>c.<.ctor>b__73_2(BuilderStrategy[] chain, BuilderContext& context)
   at Unity.Builder.BuilderContext.Resolve(Type type, String name, InternalRegistration registration)
   at Unity.Builder.BuilderContext.Resolve(Type type, String name)
   at Unity.Builder.BuilderContext.Resolve(ParameterInfo parameter, Object value)
   at Unity.Processors.ConstructorProcessor.<>c__DisplayClass16_0.<GetResolverDelegate>b__0(BuilderContext& c)
   at Unity.Processors.MemberProcessor`2.<>c__DisplayClass8_0.<GetResolver>b__0(BuilderContext& c)
   at Unity.Processors.MemberProcessor`2.<>c__DisplayClass8_0.<GetResolver>b__0(BuilderContext& c)
   at Unity.Processors.MemberProcessor`2.<>c__DisplayClass8_0.<GetResolver>b__0(BuilderContext& c)
   at Unity.Strategies.BuildPlanStrategy.PreBuildUp(BuilderContext& context)
   at Unity.UnityContainer.<>c.<.ctor>b__73_2(BuilderStrategy[] chain, BuilderContext& context)
   at Unity.Builder.BuilderContext.Resolve(Type type, String name, InternalRegistration registration)
   at Unity.Builder.BuilderContext.Resolve(Type type, String name)
   at Unity.Builder.BuilderContext.Resolve(ParameterInfo parameter, Object value)
   at Unity.Processors.ConstructorProcessor.<>c__DisplayClass16_0.<GetResolverDelegate>b__0(BuilderContext& c)
   at Unity.Processors.MemberProcessor`2.<>c__DisplayClass8_0.<GetResolver>b__0(BuilderContext& c)
   at Unity.Processors.MemberProcessor`2.<>c__DisplayClass8_0.<GetResolver>b__0(BuilderContext& c)
   at Unity.Processors.MemberProcessor`2.<>c__DisplayClass8_0.<GetResolver>b__0(BuilderContext& c)
   at Unity.Strategies.BuildPlanStrategy.PreBuildUp(BuilderContext& context)
   at Unity.UnityContainer.<>c.<.ctor>b__73_1(BuilderContext& context)
   at Unity.UnityContainer.Unity.IUnityContainer.Resolve(Type type, String name, ResolverOverride[] overrides)
   at System.Web.Mvc.DefaultControllerFactory.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType)
   --- End of inner exception stack trace ---
   at System.Web.Mvc.DefaultControllerFactory.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType)
   at System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory)
   at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
   at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStepImpl(IExecutionStep step)
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)````

1 Ответ

0 голосов
/ 20 февраля 2020

Добавить пустой конструктор, как;

public PersonController() {};    
//before 

public PersonController(ICrudService<Person> personCrudservice) 
{
  this.personCrudservice = personCrudservice;
};
...