实体框架自跟踪实体和 ASP MVC .NET 以及托管可扩展性框架的问题

发布于 2024-09-10 10:02:36 字数 1225 浏览 1 评论 0原文

大编辑:这个问题可能是由 MEF 引起的!

我正在使用面向服务的架构,并让我的所有 MVC 控制器通过服务执行操作。

我有一个如下所示的基本服务:

public abstract class BaseService
{    
     protected MyObjectModel context;

     public BaseService()
     {
          context = new MyObjectModel();
     }
}

然后我有继承的服务

[Export(typeof(IEmployeeService))]    
public class EmployeeService : BaseService, IEmployeeService
    {
         public void NewEmployee(Employee newEmployee)
         {
              context.Employees.AddObject(newEmployee);
              context.SaveChanges();
         }
    }

我的控制器也从一个基类继承,该基类提供对所有必需服务的访问,以便他们可以调用:

EmployeeService.AddEmployee(new Employee() { Name = "JohnDoe"});

这一切都工作得很好,直到我开始看到ObjectContext 没有准确地反映构建时的数据库。

我在 BaseService 构造函数中放置了一个断点,并使用 Sql Server 的 Profiler 发现全新的 MyObjectModel 甚至没有访问数据库,而是从某些缓存中提取数据?

我偶然发现了上下文中集合的 MergeOption 属性,并进行了更改以确保数据是最新的,但现在我每次创建返回实体的新服务方法时都需要使用它!

编辑: 我一直在跌跌撞撞地前进,直到我意识到我的问题可能是由 MEF 引起的。

我已经覆盖了默认的 ControllerFactory 并实现了一个使用 MEF 来实例化服务的控制器工厂。我可能看到的是 MEF 在调用之间保持对象处于活动状态。

那么

1)我在哪里可以阅读有关此行为的更多信息?我该如何阻止它并在每次调用该对象时强制进行新的组合?

谢谢。

BIG EDIT: This problem is probably being caused by MEF!

I'm using a service oriented architecture and have all my MVC controllers perform actions through the services.

I have a base service that looks like this:

public abstract class BaseService
{    
     protected MyObjectModel context;

     public BaseService()
     {
          context = new MyObjectModel();
     }
}

I then have services that inherit

[Export(typeof(IEmployeeService))]    
public class EmployeeService : BaseService, IEmployeeService
    {
         public void NewEmployee(Employee newEmployee)
         {
              context.Employees.AddObject(newEmployee);
              context.SaveChanges();
         }
    }

I have my controllers also inheriting from a base class that provides access to all the required services so they can just call:

EmployeeService.AddEmployee(new Employee() { Name = "JohnDoe"});

This all worked wonderfully until I started seeing that the ObjectContext wasn't accurately reflecting the database upon construction.

I put a breakpoint in the BaseService constructor and using Sql Server's Profiler saw that the brand new MyObjectModel wasn't even hitting the DB but pulling the data out of some cache presumably?

I stumbled upon the MergeOption property of the collections in the context and changing that made sure the data was fresh, but now I need to use that everytime I create a new service method that returns entities!

EDIT:
I've been stumbling along until I realised that my issues were probably being caused by MEF.

I have overridden the default ControllerFactory and implemented one that uses MEF to instantiate the services. What I'm probably seeing is MEF keeping the objects alive between calls.

So

1) Where can I read more on this behaviour? And what can I do to stop it and force a fresh composition every time the object is called?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

几味少女 2024-09-17 10:02:36

经过几个小时的拔头发后,我最终解决了这个问题。

我的 ControllerFactory 实现如下所示。

public class ControllerFactory : IControllerFactory
    {
        CompositionContainer container;
        DefaultControllerFactory controllerFactory;

        public ControllerFactory()
        {
            container = new CompositionContainer(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
            controllerFactory = new DefaultControllerFactory();
        }

        public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
        {
            var controller = controllerFactory.CreateController(requestContext, ControllerName);

            container.ComposeParts(controller);

            return controller;
        }

        public void ReleaseController(IController controller)
        {
            var disposable = controller as IDisposable;
            if (disposable != null)
            {
                disposable.Dispose();
            }
        }
    }

我在我的应用程序启动中调用了这一行。

ControllerBuilder.Current.SetControllerFactory(new ControllerFactory());

发生的情况是控制器工厂每个 AppDomain 周期仅初始化一次,因此我的组合容器也是如此。我的服务类没有专门标记为共享或非共享使用,因此容器保留了每个服务类的引用。每次 ControllerFactory 在每次调用时创建一个新控制器时,它都会使用上次调用时仍然保留的引用来填充服务属性,包括导致数据不匹配的旧 ObjectContext。

我的整个问题是通过

[PartCreationPolicy(CreationPolicy.NonShared)]

每次添加到每个服务并强制执行新版本来解决的。

现在我想知道 MEF 是否仍然保留这些引用,因为 ObjectContext 不是一个需要保留的小东西。这是即将发生的内存泄漏吗?

I solved this issue eventually after hours of pulling out my hair.

My implementation of ControllerFactory looked like this.

public class ControllerFactory : IControllerFactory
    {
        CompositionContainer container;
        DefaultControllerFactory controllerFactory;

        public ControllerFactory()
        {
            container = new CompositionContainer(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
            controllerFactory = new DefaultControllerFactory();
        }

        public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
        {
            var controller = controllerFactory.CreateController(requestContext, ControllerName);

            container.ComposeParts(controller);

            return controller;
        }

        public void ReleaseController(IController controller)
        {
            var disposable = controller as IDisposable;
            if (disposable != null)
            {
                disposable.Dispose();
            }
        }
    }

And I called this line in my Application Startup.

ControllerBuilder.Current.SetControllerFactory(new ControllerFactory());

What was happening was that the controller factory was only being initialised once per AppDomain cycle and therefore my composition container was as well. My service classes weren't marked specifically for Shared or Non Shared usage, so the container held onto a reference of each one. Every time the ControllerFactory created a new controller on each call it would populate the service properties with the references it still held from the last call, including the old ObjectContext which was resulting in the mismatch in data.

My entire problem was solved by adding

[PartCreationPolicy(CreationPolicy.NonShared)]

to each service enforcing a fresh version each time.

Now I'm left to wonder if MEF is STILL holding onto thos references, because that ObjectContext is not a small thing to hold onto. Is this a memory leak waiting to happen?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文