DbContext.Set和其他地方的实体框架ASP.NET MVC(有时)问题

问题描述 投票:1回答:1

使用ASP.NET与Entity Framework和Unity Container结合使用时,出现了一个奇怪的问题。

此问题在应用程序运行了几小时到几天后发生。并且在这种情况发生之后,通过重新启动IIS在时间上是固定的(也是同一时期)。

有时,在尝试注入(使用统一容器)控制器时,该问题给出了例外。

示例:

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.

当然,控制器没有无参数的构造函数,但是使用unity-container注入了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>()
            );
    }
}

我现在已经遇到这个问题了几周了,尝试使用不同的LifeTimeManagers并降级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)````
c# entity-framework entity-framework-6 unity-container asp.net-mvc-5.2
1个回答
-1
投票
public PersonController() {}; //before public PersonController(ICrudService<Person> personCrudservice) { this.personCrudservice = personCrudservice; };
© www.soinside.com 2019 - 2024. All rights reserved.