Реализация CRUD с использованием интерфейса - PullRequest
11 голосов
/ 21 сентября 2010

Каков наилучший подход для реализации CRUD на BL с использованием интерфейса, который будет использоваться для абстрагирования операций DAL? Мне нужно ваше мнение, ребята ..

Вот мой черновик ..

Объекты данных, которые отображаются в таблице базы данных

 public class Student
 {
    public string StudentId { get; set; }
    public string StudentName { get; set; }
    public Course StudentCourse { get; set; }
 }

 public class Course
 {
    public string CourseCode { get; set; }
    public string CourseDesc { get; set; }
 }

Я создал интерфейс CRUD для абстрагирования операций объекта

public interface IMaintanable<T>
{
   void Create(T obj);
   T Retrieve(string key);
   void Update(string key);
   void Delete(string key);
 }

И затем компонент, который управляет сущностью и ее операциями, реализуя интерфейс

public class StudentManager : IMaintainable<Student>
{
    public void Create(Student obj)
    {
        // inserts record in the DB via DAL
    }

    public Student Retrieve(string userId)
    {
        // retrieveds record from the DB via DAL
    }

    public void Update()
    {
        // should update the record in the DB
    }

    public void Delete(string userId)
    {
        // deletes record from the DB
    }
}

пример использования

    public void Button_SaveStudent(Event args, object sender)
    {
        Student student = new Student()
        {
           StudentId = "1", StudentName = "Cnillincy"
        }

        new StudentManager().Create(student);   
     }

как видите, в методе обновления есть некоторые отклонения

    public void Update()
    {
        // should update the record in the DB
    }

что должен иметь этот метод для обновления свойства objects? я должен унаследовать Студент ?

    public class StudentManager : Student , IMaintainable<Student>
    {
        public void Update()
        {
            //update record via DAL
         }
    }


    public void Button_SaveStudent(Event args, object sender)
    {
        Student student = new StudentManager();
        student.StudentId = "1";
        student.StudentName = "Cnillincy"
        student.Update()
    }

Или я должен просто указать класс Student в качестве атрибута менеджера Student?

     public class StudentManager : IMaintainable<Student>
    {
        public Student student { get; private set };

        public void Create() {}
        public void Update() {}
        public void Retrieve() {}
        public void Delete() {}
    }

Что более уместно? А как насчет интерфейса? Любые другие предложения, ребята? thanks..C

Ответы [ 6 ]

15 голосов
/ 21 сентября 2010

Ваш интерфейс CRUD, вероятно, должен выглядеть как

public interface IMaintanable<T>
{
    string Create(T obj);
    T Retrieve(string key);
    void Update(T obj);
    void Delete(string key);
}

, то есть Create и Update берут копию обновляемого объектаРазница в том, что Update может получить key от obj, поэтому он знает, какой объект он меняет.Create обычно вызывает создание ключа, поэтому вы возвращаете его в качестве возвращаемого значения.Надеюсь, это поможет.

(Обновление также может вернуть ключ назад.)

9 голосов
/ 21 сентября 2010

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

В прошлом я лично реализовывал интерфейс, определяющий репозиторий, такой как IRepository<T>,и базовый класс, который специфичен для типа репозитория, такой как SqlRepositoryBase<T>.Причина, по которой я бы сделал это, заключается в том, что я могу поместить специфичный для реализации код в базовый класс.Итак, работа выполнена, и я могу беспокоиться о реализации для конкретного домена в конечном хранилище, которое будет StudentRepository, SqlRepository<Student> (или SqlRepository<IStudent>, если вы определите интерфейсы для вашей сущности).

Кажется, вы обеспокоены тем, сколько объектов создано, и я могу вам сказать, что вы не генерируете достаточно значительную утечку ресурсов, чтобы действительно задумываться о реализации таким способом.Старожилы могут смущаться этому факту, но мы больше не пытаемся оптимизировать работу под 64 КБ или ОЗУ.;-) Это больше о возможности сопровождения, контрактах кода и т. Д.

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

Вот несколько полезных ссылок по этим темам:

Два вывода из этого в целом (ИМХО):

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

  • Самый большой плюс этого подхода - этоявная проверяемость этого;даже больше, чем возможность повторного использования.Если вы хотите макетировать свои репозитории для какого-либо подхода TDD, вы можете сделать это без особых усилий.Это позволит вам писать более подробные тесты по использованию репозиториев в вашем коде.

3 голосов
/ 21 сентября 2010

Я видел это от Роба Конери, которое мне действительно нравится. Его сила в гибкости аргументов, которые вы можете передать методам. Ваша имплиментация не является достаточно надежной ИМО. Проверьте его стартовый комплект MVC здесь http://mvcstarter.codeplex.com/ (он называется ISession там).

public interface IMaintainable : IDisposable
    {
       T Single<T>(Expression<Func<T, bool>> expression) where T : class, new();
       System.Linq.IQueryable<T> All<T>() where T : class, new();
       void Add<T>(T item) where T : class, new();
       void Update<T>(T item) where T : class, new();
       void Delete<T>(T item) where T : class, new();
       void Delete<T>(Expression<Func<T, bool>> expression) where T : class, new();
       void DeleteAll<T>() where T : class, IEntity, new();
       void CommitChanges();
    }
1 голос
/ 21 сентября 2010

Я бы не заставлял StudentManager наследовать Student, я бы сделал свой метод Update без сохранения состояния, как и ваш метод create, т.е.

public interface IMaintanable<T>
{
  void Create(T obj);
  T Retrieve(string key);
  void Update(T obj);
  void Delete(string key);
}

и

public void Update(T obj)
{
  // should update the record in the DB
}
0 голосов
/ 11 сентября 2014

Я немного изменил ответы здесь:

public interface IMaintanable<T>
{
    Guid Create(T obj);
    T Read(Guid key);
    bool Update(T obj);
    bool Delete(Guid key);
}

Этот интерфейс основан на моей структуре базы данных. Я использую направляющие для первичных ключей.

0 голосов
/ 21 сентября 2010

Взгляните на новую Entity Framework 4 , которая была недавно выпущена. Они имеют модель «код по соглашению», которая позволяет легко сопоставлять ваши бизнес-объекты непосредственно с базой данных, не беспокоясь о DAL.

"The Gu" имеет замечательную серию , в которой описывается, как легко наносить на карту ваши объекты, и даже вносить некоторые простые изменения при связывании с базой данных через используемую модель DbContext.

Стоит отметить, что текущий выпуск находится на CTP4, но я ожидаю, что большинство проблем уже проработано с фреймворком и должно хорошо вам помочь.

...