Внедрение CRUD с использованием интерфейса

Каков наилучший подход для реализации 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);
 }

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

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
    }

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

    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

Ответ 1

Ваш интерфейс 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 обычно вызывает создание ключа, поэтому вы передаете его обратно как возвращаемое значение. Надеюсь, что это поможет.

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

Ответ 2

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

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

Похоже, вы обеспокоены тем, сколько объектов инстансируется, и я могу сказать вам, что вы не генерируете достаточно значительную утечку ресурсов, чтобы действительно быть заинтересованы в реализации таким образом. Старожилы могли бы съежиться от этого факта, но мы больше не пытаемся оптимизировать для 64k или RAM.;-) Это больше касается ремонтопригодности, кодовых контрактов и т.д.

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

Вот несколько хороших ссылок для этих тем:

Два вылета из этого в целом (IMHO):

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

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

Ответ 3

Я видел это от Роба Конери, что мне очень нравится. Это сила в гибкости аргументов, которые вы можете передать методам. Ваша эксплоатация недостаточно устойчива к ИМО. Посмотрите его стартовый комплект 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();
    }

Ответ 4

Я бы не стал наследовать StudentManager наследовать, я бы сделал мой метод 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
}

Ответ 5

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

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

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

Ответ 6

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

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

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