2010-07-19 2 views
2

BIG EDIT: эта проблема, вероятно, вызвана MEF!Проблемы с объектами самообучения Entity Framework и ASP MVC .NET и управляемая расширяемость Framework

Я использую сервис-ориентированную архитектуру и все мои контроллеры 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"}); 

Все это работало wo когда я начал видеть, что ObjectContext не точно отражает базу данных при построении.

Я установил точку останова в конструкторе BaseService и с помощью профилировщика Sql Server увидел, что новый MyObjectModel даже не попал в БД, но вытащил данные из некоторого кеша предположительно?

Я наткнулся на свойство MergeOption коллекций в контексте и изменил это, чтобы данные были свежими, но теперь мне нужно использовать это каждый раз, когда я создаю новый метод службы, который возвращает сущности!

EDIT: Я спотыкался, пока не понял, что мои проблемы, вероятно, вызваны 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 STILL держаться за эти ссылки, потому что этот ObjectContext не является маленькой вещью. Ожидается ли утечка памяти?

+0

Возможно, лучше создать отдельный CompositionContainer для каждого запроса. Тогда вам не придется беспокоиться о том, что MEF держится за ссылки (что будет, если части реализуют IDisposable). Вы можете создать каталог один раз, а затем создать CompositionContainer, используя этот каталог для каждого запроса. –

+0

Каковы затраты, связанные с созданием CompositionContainer в каждом запросе? Они достаточно малы, чтобы игнорировать? Похоже, это правильный путь ... –

+0

И на какой стадии я должен создавать этот контейнер, на фабрике контроллера? Я хочу создать единый ObjectContext для каждого запроса и поделиться им среди моих сервисов. Является ли контроллер фабрикой местом для этого? –

Смежные вопросы