2

или один из наших проектов (C# Windows Service, в основном для обработки данных из внешних ресурсов и чтения/записи этих данных в базу данных SQL Server), мы реализовали шаблон хранилища в DAL, и мы создали класс репозитория для каждого POCO (который представляет собой таблицу). Использование этих классов репозитория управляется шаблоном Unit of Work, поэтому все репозитории совместно используют один и тот же DbContext в одной единице работы, но, возможно, это не имеет отношения к вопросу.Шаблон репозитория Framework Entity Framework в DAL, как реализовать функции обновления?

Репозиторий класс для, скажем, объект клиента, осуществляется следующим образом:

public class CustomerRepository 
{ 
    private readonly MyContext _context; 
    public CustomerRepository(MyContext context) 
    { 
     _context = context; 
    } 

    public Customer GetCustomer(string id) 
    { 
     return _context.Customers.Find(new object[] {id}); 
    } 

    public IEnumerable<Customer> GetAllCustomers(Func<Customer,bool> predicate) 
    { 
     return _context.Customers.Where(predicate); 
    } 
    public IEnumerable<Customer> GetCustomerByCity(string city) 
    { 
     return _context.Customers.Where(c=>s.City.Equals(city)); 
    } 


    public void SetAge(string id, byte age) 
    { 
     _context.Customers.Find(new object[] { id }).Age = age; 
    } 

    public void Update(Customer customer) 
    { 
     _context.Entry(customer).State = EntityState.Modified; 
    } 

} 

Теперь у меня есть несколько вопросов о том, что лучшая практика для обновления-методов:

  • Рекомендуется ли иметь отдельные методы для обновления определенных полей в базе данных, например метода SetAge()?
  • Или Рекомендуется получить объект Customer для нашего BLL (с ​​GetCustomer (id)) и просто установить свойства в BLL как customer.Age = 35 ;, а затем сохранить эти изменения?

Операции обновления в основном ограничиваются одним полем в одной строке.

Может быть, кто-нибудь хотел бы поделиться с нами некоторыми реальными мыслями?

+0

Если вы думаете о практичности, имеющих определенную операцию обновления для всех свойств, то ответ достаточно очевиден. Кроме того, такой подход, вероятно, не будет масштабироваться очень хорошо, учитывая, что вы будете делать несколько поездок в БД для обновления одного и того же объекта. – James

+1

@James Операции обновления в основном ограничиваются одним полем в одной строке, поэтому наличие нескольких обращений в оба конца здесь не является проблемой. Насколько это уместно, изменения отслеживаются Entity Framework (изменения остаются в памяти), и запись будет передана базе данных за одну поездку при вызове SaveChanges на нашем объекте контекста. – Jeroen1984

+1

хорошо для меня, 'SetAge' является логикой домена и, как таковой, действительно не принадлежит слою репозитория. Если вы спрашиваете, есть ли какой-либо * вред * при выполнении того, что вы делаете, тогда ответ отрицательный. Однако рассматривать такие вещи, как влияние редактирования объекта, будет, например, удаление/переименование свойства или добавление нового свойства. Все, что вы действительно делаете, это лишняя дополнительная работа, EF достаточно умна, чтобы обновлять только то, что изменилось. – James

ответ

1
  • Рекомендуется ли использовать отдельные методы для обновления определенных полей в базе данных, например метод SetAge()?

Я не думаю, что было бы разумно иметь отдельные операции для каждого объекта. Вы получите методы инкапсуляции свойств. Кроме того, вместо того, чтобы внедрять методы для каждого типа, почему бы не создать базовый репозиторий для выполнения операций с commmon? Вместо GetAllCustomers вы можете реализовать GetAll в базовом классе и получить все ваши репозитории из этого базового хранилища.

  • Или это рекомендуется, чтобы получить объект клиента к нашему УСК (с GetCustomer (ID)), а просто установить свойства в УСК как customer.Age = 35 ;, а затем сохранить эти изменения?

Я думаю, что проблема не в том, где вы меняете свойства, проблема в том, что anemic domain model. У вас есть отдельный бизнес-уровень, который изменяет объекты с использованием методов репозитория. Это нарушает ориентированный на объект подход, который диктует, что объекты должны иметь как свойства, так и методы.

+0

Модели Entity Framework - это объекты DTO, а не объекты домена. Объектом домена, содержащим бизнес-логику, будет Клиент, который проверяет, установлен ли возраст, по крайней мере, '0'. – CodeCaster

+0

@CodeCaster Это не мешает вам иметь объекты домена из сгенерированного кода; также я не видел ничего, указывающего EF в вопросе. – daryal

+0

Это DAL, а не BL. Мы ничего не знаем о BL OP. Для EF см. Теги вопроса. – CodeCaster

2

Я склонен согласиться с Дарьялом. Но подчеркнуть, что у вас нет спокойной модели класса репозитория. В идеале вы хотите, чтобы репозиторий был общим. Работайте над объектами Full и предоставляйте службы DAL.

public class DAL.Repository<poco> { 

    //methods for CRUD, get List, search whatever you see as right 
    // eg ...add error handling.... 
    void add(poco p){ 
     context.attach(p); 
    ... 
} 


// The domain/core model layer would have much of the object based business logic 
public class CORE.PocoXYZ { 
    //all the get sets and methods required to manipulate the object 
} 


// And your Unit of Work Class 
Public class DAL.UoW{ 
    context.savechanges(); 
} 


So i would suggest you perform object level Data storage in the DAL. But do all teh object manipulation in the core. The DAL would control the save in a UoW class that managed all Repositories. 

Сервис или слой пользовательского интерфейса может вводить слой UoW/Repository в слой Core.

4

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

Что-то думать о ...

+0

О, нет, я думал, что я был на правильном пути с этой реализацией, но это может изменить мой образ мыслей. Можете ли вы рассказать мне, почему некоторые учебные пособия предлагают этот подход (например, http://www.asp.net/mvc/tutorials/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and- unit-of-work-patterns-in-as-asp-net-mvc-application)? Я немного запутался в том, что реализовать сам, и в каком слое моего приложения ... – Jeroen1984

+0

Хорошо, эта статья использует шаблон UOW для инкапсуляции Контекста и репозиториев, чтобы вы могли тестировать единицу без попадания в базу данных , Опять же, это только мое личное мнение, но я не согласен с этой философией. Изменение схемы БД - слишком частое дело, и если вы не нажимаете фактический тестовый сервер Sql (или любую другую базу данных, которую используете), как вы можете узнать, изменилось ли ваше изменение базы данных в совершенно другом метод, чем тот, который вы тестируете? IMO, вам нужно попасть в БД, когда вы тестируете блок. Другие со мной не согласятся. – Scottie

+1

Что касается того, какие слои делают то, что я делаю ... Я создаю приложение MVC как верхний слой, а затем бизнес-логику под этим, а затем под EntityModel. Я немного обманываю T4 и фактически создаю 4-й проект, в котором все проекты имеют доступ к которым содержатся POCOs. BusinessLogic действительно отвечает за все доступ к БД. Ваш уровень MVC будет вызывать уровень бизнес-логики, который НИКОГДА не должен возвращать IQueryable. На этом этапе всегда должен быть ICollection. Если вам нужна дополнительная помощь, напишите мне по адресу scottieslg в gmail dot com, и я буду рад помочь. – Scottie

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