2010-07-19 71 views
2

BIG编辑:此问题可能是由MEF造成的!实体框架自我跟踪实体和ASP MVC .NET和托管扩展框架的问题

我正在使用面向服务的体系结构,并让我所有的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"}); 

This all worked wo直到我开始看到ObjectContext没有准确反映数据库的构建。

我在BaseService构造函数中添加了一个断点,并且使用Sql Server的Profiler发现全新的MyObjectModel甚至没有触及数据库,但是可能推断出某些缓存中的数据?

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

编辑: 我一直沿着直到我意识到我的问题很可能是由MEF引起的绊脚石。

我重写了默认的ControllerFactory并实现了一个使用MEF实例化服务的实例。我可能看到的是MEF在呼叫之间保持对象的活动。

所以

1)我在哪里可以阅读更多的这种行为?我能做些什么来阻止它,并在每次调用对象时强制一个新组合?

谢谢。

回答

1

我在拔出头发数小时后最终解决了这个问题。

我的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是否仍然支持thos引用,因为ObjectContext不是一件小事。这是一个内存泄漏等待发生?

+0

为每个请求创建一个单独的CompositionContainer可能会更好。那么你将不必担心MEF坚持引用(如果这些部分实现了IDisposable)。您可以创建一次该目录,然后使用该目录为每个请求创建一个CompositionContainer。 – 2010-07-20 05:46:21

+0

在每个请求中创建CompositionContainer涉及哪些成本?他们小到可以忽略?听起来像这是正确的道路... – 2010-07-20 08:11:25

+0

我应该在哪个阶段创建这个容器,在控制器工厂?我想为每个请求创建一个ObjectContext,并在我的服务中共享它。控制器工厂是否应该这样做? – 2010-07-20 09:04:56