Entity Framework 4.1 Сначала код: добавление и обновление записей через уровень сервиса

#entity-framework #asp.net-mvc-3 #entity-framework-4 #entity-framework-4.1

#entity-framework #asp.net-mvc-3 #entity-framework-4 #entity-framework-4.1

Вопрос:

Сначала я использую код Entity Framework 4.1 и ASP.NET MVC 3.

У меня есть класс service, и в этом классе я вызываю свои методы репозитория.

Я получил добавление нового объекта tutorial для работы, я просто не знаю, как обновить запись. Вот мои методы вставки и обновления для сервиса:

 public class TutorialService : ITutorialService
{
   private ITutorialRepository tutorialRepository;

   public TutorialService(ITutorialRepository tutorialRepository)
   {
      this.tutorialRepository = tutorialRepository;
   }

   public void Insert(Tutorial tutorial)
   {
      tutorialRepository.Add(tutorial);
      tutorialRepository.Save();
   }

   public void Update(Tutorial tutorial)
   {
      // Not sure what the code looks like here to call the repo methods
   }
}
  

Мой класс репозитория:

 public class TutorialRepository : ITutorialRepository
{
   PbeContext db = new PbeContext();

   public void Add(Tutorial tutorial)
   {
      db.Tutorials.Add(tutorial);
   }

   public void Save()
   {
      db.SaveChanges();
   }
}
  

Класс контроллера:

 public ActionResult Edit(EditTutorialViewModel editTutorialViewModel)
{
   // Other code

   if (!ModelState.IsValid)
   {
      return View("Edit", editTutorialViewModel);
   }

   // Mapping code here to Tutorial object
   Tutorial tutorial = (Tutorial)tutorialMapper.Map(editTutorialViewModel, typeof(EditTutorialViewModel), typeof(Tutorial));

   // Update the existing tutorial
   tutorialService.Update(tutorial);

   return RedirectToRoute(Url.TutorialList());
}
  

Как будет выглядеть код обновления? Есть ли более простой способ сделать это?

Ответ №1:

В вашем репозитории:

 public void UpdateScalar(Tutorial tutorial)
{
    var original = db.Tutorials.Find(tutorial.ID);
    db.Entry(original).CurrentValues.SetValues(tutorial);
}
  

А затем в вашем сервисе:

 public void Update(Tutorial tutorial)
{
    tutorialRepository.UpdateScalar(tutorial);
    tutorialRepository.Save();
}
  

Решение Tigger тоже работает и имеет то преимущество, что нет необходимости загружать оригинал перед обновлением. С другой стороны, установка состояния на Modified приводит к тому, что все свойства отправляются в базу данных в инструкции UPDATE, независимо от того, изменились они или нет. Решение, описанное выше, только отправляет измененные свойства в базу данных, но требует предварительной загрузки оригинала.

Оба решения работают только со скалярными свойствами. Как только задействованы более сложный граф объектов и свойства навигации, обновление становится более сложным.

Комментарии:

1. Спасибо. Когда EF создает за вас ваши SQL-инструкции, не возникают ли иногда проблемы с производительностью? Можете ли вы точно настроить их?

2. На самом деле это не связано с исходным вопросом, но в чем разница между Find и Get?

3. @Brendan Vogt: Вы в значительной степени привязаны к операторам SQL, генерируемым EF. Вы не можете это контролировать. Хотя есть варианты прямой отправки написанной от руки SQL-команды на сервер, но это только для очень особых ситуаций. Для «обычных» операций CRUD я бы использовал SQL, сгенерированный EF. Что вы имеете в виду, говоря «Получить»? Find загружает объект по его ключу, и если он уже загружен, он возвращает только ссылку на объект, который находится в контексте. Это не подходит для общих запросов. В этом случае обычно используется запрос LINQ с Where оператором.

Ответ №2:

Вы могли бы использовать один и тот же метод сохранения в классе репозитория как для вставки, так и для обновления, например,

 public void Save(Tutorial tutorial)   
{   
   db.Entry(tutorial).State = tutorial.Id == 0
                                     ? EntityState.Added
                                     : EntityState.Modified;

   db.SaveChanges();   
}