2010-09-21 5 views
11

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

Вот мой проект ..

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

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 
    } 

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

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

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

 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

ответ

14

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

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

+0

Вы считаете, что это более эффективно, чем наследование объекта, потому что это означает, что вы создадите другую копию obj вместо того, чтобы просто обновлять ее. – CSharpNoob

+2

Наследование не имеет смысла. Ваш StudentManager НЕ является студентом. – Matthieu

+0

Что сказал Маттие. Подумайте о студенте, как о записи, и о вашем студенческом менеджере, таком как секретарь директора, набрав записи, когда они входят. Принцип единой ответственности FTW. – Lunivore

0

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

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 
} 
+2

Не могли бы вы объяснить, почему это более уместно, чем наследование или атрибуция DataEntity? спасибо – CSharpNoob

+1

Для меня это до ОО «правильность» и разделение проблем; Студенческий менеджер не является студентом (в смысле ОО). Ответственность классов студентов заключается в том, чтобы моделировать данные, ответственность Студентов-менеджеров заключается в сохранении этих данных, я просто думаю, что они не должны смешиваться. Но это просто мое мнение, я могу быть не прав :) – JonoW

2

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

это как IEnumerable методы расширения .. спасибо – CSharpNoob

+0

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

+0

@JamesSouth получает ошибку при ключевом слове IEntity –

9

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

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

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

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

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

Два вынос из этого вообще (ИМХО):

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

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

+1

Подобный шаблон CRUD похож на шаблон репозитория в любом случае, как бы вы его ни называли. Я согласен с вашими комментариями, что это полезно даже для небольших проектов. Хорошая вещь о приближении к ней с точки зрения CRUD заключается в том, что она отлично переводится в REST. REST, даже сделанный плохо, довольно эффективен и масштабируемо. С таким доменом, как студенты - доступ к нему в течение всего нескольких дней каждый год - производительность может быть предметом рассмотрения, даже если это не дифференциатор. – Lunivore

+0

Джозеф, спустя годы все еще ценный, как таковая ссылка на «Единица рабочего шаблона» сломана, можете ли вы это обновить? – Edward

+0

@Edward - сделано. Использовал Wayback Machine, чтобы вытащить его. Благодаря! –

0

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

«Gu» имеет great series, в котором излагаются, как легко отображать ваши объекты и даже выполнять некоторые простые изменения при привязке к базе данных с помощью модели DbContext, которую она использует.

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

0

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

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

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

+1

Может быть, хорошо объяснить, почему вы предлагаете изменение ... –

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