#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();
}