Вопрос

Я использую "Техника заглушки" к Обновить Мой Poco (используется в отдельном контексте, ASP.NET MVC).

Это код, который у меня сейчас есть в моем контроллере (который работает):

[HttpPost]
public ActionResult Edit(Review review)
{
   Review originalReview = _userContentService.FindById(review.PostId) as Review;
   var ctx = _unitOfWork as MySqlServerObjectContext;
   ctx.ApplyCurrentValues("MyEntities.Posts", review);
   _unitOfWork.Commit();
   // ..snip - MVC stuff..
}

Как видите, везде есть код кода. :)

Несколько баллов:

  1. Я использую инъекцию зависимости (на основе интерфейса) для в основном все
  2. Я использую единицу рабочего шаблона в абстрактный объектContextext и обеспечить постоянство в нескольких репозиториях
  3. В настоящее время мой INITITOFWORK Интерфейс имеет только 1 метод: void Commit();
  4. Контроллер есть IUserContentService а также IUnitOfWork вводить ди
  5. IUserContentService вызовы Find в репозиториях, которые используют ObjectContext.

Это две вещи, которые мне не нравятся с моим вышеуказанным кодом:

  1. Я не хочу бросать INITITOFWORK так как MySqlServerObjectContext.
  2. Я не хочу, чтобы контроллер должен был заботиться о ApplyCurrentValues

Я в основном хочу, чтобы мой код выглядел так:

[HttpPost]
public ActionResult Edit(Review review)
{
   _userContentService.Update(review);
   _unitOfWork.Commit();
   // ..snip - MVC stuff..
}

Любые идеи, как я могу это сделать? (или что-то подобное).

У меня уже есть Smarts для того, чтобы выработать имя набора сущности на основе типа (комбинация дженериков, плюрализации), поэтому не беспокойтесь об этом.

Но Мне интересно, где лучшее место, чтобы поставить ApplyCurrentValues является? Похоже, это не подходит, чтобы положить его в IUnitOfWork Интерфейс, так как это проблема настойчивости (EF). По той же причине это не принадлежит в сервисе. Если я положу это в мой MySqlServerObjectContext Класс (имеет смысл), где бы я назвал это, так как ничего непосредственно не имеет доступа к этому классу - он вводится через DI, когда что-то запрашивает IUnitOfWork.

Есть предположения?

РЕДАКТИРОВАТЬ

У меня есть решение ниже, используя технику заглушки, но проблема в том, что если бы я получил сущность, которую я заранее обновляю, он бросает исключение, заказывая сущность с этим ключом уже существует.

Что имеет смысл, хотя я не уверен, как это может решить?

Должен ли мне «проверить, уже подключен ли объект, если нет, приложите его?»

Может ли какие-нибудь эксперты EF4 есть помощь?

РЕДАКТИРОВАТЬ

Nevermind - нашел решение, см. Ответ ниже.

Это было полезно?

Решение

Выяснил это - было нелегко, поэтому я постараюсь объяснить все возможное. (Для тех, кто заботится)

Контрольный код контроллера:

// _userContentService is IUserContentService
_userContentService.Update(review);

Итак, мой контроллер называет методом под названием Update на IUserContentService, проходя через сильно набранный Review объект.

Услуги пользовательского контента Соответствующий код

public void Update(Post post)
{
   // _userContentRepository is IPostRepository
   _userContentRepository.UpdateModel(post);
}

Итак, мой сервис вызывает метод под названием UpdateModel на IPostRepository, проходя через сильно набранный Review объект.

Теперь, вот сложная часть.

У меня на самом деле есть Нет конкретных репозиториев. Отказ у меня есть Общий репозиторий называется GenericRepository<T> : IRepository<T>, который обрабатывает Все разные репозитории.

Поэтому, когда что-то запрашивает IPostRepository (который делал мой сервис), не даст ему GenericRepository<Post>.

Но теперь я даю это PostRepository:

public class PostRepository : GenericRepository<Post>, IPostRepository
{
   public void UpdateModel(Post post)
   {
      var originalPost = CurrentEntitySet.SingleOrDefault(p => p.PostId == post.PostId);
      Context.ApplyCurrentValues(GetEntityName<Post>(), post);
   }
}

И потому что класс происходит от Универсальный, Он наследует всю основную логику репозитории (найти, добавить и т. Д.).

Сначала я пытался поставить это Updatemodel. код в Универсальный Сам класс (а потом я бы не нуждался в этом конкретном репозитории), но проблема в том, что логика для извлечения существующего объекта основана на определенной клавише объекта, которая GenericRepository<T> не знал бы о.

Но конечный результат является шить Скрывается глубоким в глубине слоя данных, и я в конечном итоге с действительно чистым контроллером.

РЕДАКТИРОВАТЬ

Эта «Техника заглушки» также работает:

public void UpdateModel(Post post)
{
   var stub = new Review {PostId = post.PostId};
   CurrentEntitySet.Attach(stub);
   Context.ApplyCurrentValues(GetEntityName<Post>(), post);
}

Но проблема в том, что Сообщение Аннотация, я не могу создать экземпляр, и поэтому придется проверить тип поста и создавать заглушки для каждый полученный тип. Не на самом деле вариант.

Редактировать 2 (в прошлый раз)

Хорошо, получила «Техника заглушки», работающая с абстрактными классами, поэтому теперь проблема параллелизма решается.

Я добавил параметр универсального типа на мой Updatemodel. метод и особый New () ограничение.

Реализация:

public void UpdateModel<T>(T post) where T : Post, new()
{
   var stub = new T { PostId = post.PostId };
   CurrentEntitySet.Attach(stub);
   Context.ApplyCurrentValues(GetEntityName<Post>, post);
}

Интерфейс:

void UpdateModel<T>(T post) where T : Post, new();

Это мешает мне понять тип T M вручную, предотвращает вопросы параллелизма, а также предотвращает дополнительную поездку в БД.

Красивая странная.

Редактировать 3 (я думал, что в последний раз был последний раз)

Вышеуказанная «Техника заглушки» работает, но если я заранее извлеките объект, он бросает исключение, указав сущность с этим ключом, уже существует в OSM.

Может кто-нибудь посоветовать, как это справиться?

Редактировать 4 (ОК - это это!)

Я нашел решение, благодаря этому этому ответу: Можно ли проверить, уже подключен объект к контексту данных в рамках объекта?

Я пытался «проверить, прикреплен ли объект», используя следующий код:

ObjectStateEntry entry;
CurrentContext.ObjectStateManager.TryGetObjectStateEntry(entity, out entry);

Но это всегда вернулось нулевой, Даже, даже когда я исследовал OSM, я мог видеть свою сущность там с одним и тем же ключом.

Но этот код работает:

CurrentContext.ObjectStateManager.TryGetObjectStateEntry(CurrentContext.CreateEntityKey(CurrentContext.GetEntityName<T>(), entity), out entry)

Может быть, потому что я использую PIEL POCO, OSM возникла проблемы, выяснив клавишу сущности, который знает.

Ох, и еще одна вещь, которую я добавил - так что мне не нужно добавлять конкретный репозиторий для каждого объекта, я создал атрибут под названием «EntityKey"(Атрибут общественного недвижимости).

Все Poco должно быть 1 общественное свойство, украшенное этим атрибутом, или я бросаю исключение в моем модуле репозитория.

Поэтому мой универсальный репозиторий ищет это свойство для создания / настройки заглушки.

Да - он использует отражение, но это умное отражение (на основе атрибута), и я уже использую отражение для плужки на предметных именных имен от T.

Во всяком случае, проблема решена - теперь все работает нормально!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top