Шаблон репозитория и возвращаемые типы - PullRequest
6 голосов
/ 23 февраля 2012

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

Например, скажем, у меня есть следующее

Таблица предметов (вымышленная таблица)

ItemId
Name
PurchaseDate
Description
Price

В моем коде я создаю объект с полями выше под названием Item.cs (в настоящее время не использует orm).

Если у меня есть несколько сценариев, куда мне нужно вернуться

  1. ItemId
  2. комбинация даты покупки и имени
  3. ItemId и цена

Какой подход лучше?

  1. Получить все поля из таблицы предметов и вернуть объект Item (1 запрос репо)
  2. Создайте три запроса в репо и верните объект Item для каждого
  3. Создать три запроса в репо и вернуть только то, что нужно?

Теперь представьте этот сценарий с таблицей, содержащей более 10 полей.

Лично мне нравится первый вариант, но я не уверен, есть ли лучший способ сделать это.

Ответы [ 5 ]

7 голосов
/ 23 февраля 2012

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

Возвращение IQueryable - это утечка абстракции.

Взгляните на Domain Driven Design (книга), и вы получите хорошее представление о том, как должны выглядеть хорошо спроектированные репозитории.

Я также написал статью о репозиториях общего назначения:http://blog.gauffin.org/2012/02/generic-repositories-a-silly-abstraction-layer/

7 голосов
/ 23 февраля 2012

Я лично использую репозиторий универсального типа, и у меня есть чтение AsQueryable()

Вот интерфейс.

interface IRepository<T>
{
    void Create(T item);
    IQueryable<T> Retrieve();
    void Update(T item);
    void Delete(T item);
    void SubmitChanges();
}

и вот реализация.

public class PersonsRepository : IRepository<Person>
{
    private DataContext dc;

    public PersonsRepository(DataContext dataContext)
    {
        dc = dataContext;
    }

    public void Create(Person Person)
    {
        dc.Persons.Add(Person);
    }

    public IQueryable<Person> Retrieve()
    {
        IQueryable<Person> Person = (from s in dc.Persons
                                       select s);
        return Person.AsQueryable();

    }

    public void Update(Person Person)
    {
        Person _Person = (from s in dc.Persons
                            where s.ID == Person.ID
                            select s).Single();
        {
            _Person.LastLogin = Person.LastLogin;
            _Person.Password = Person.Password;
            _Person.LastUpdate = Person.LastUpdate;
            // Cannot change your username.
        }
    }

    public void Delete(Person Person)
    {
        dc.Persons.Remove(Person);
    }

    public void SubmitChanges()
    {
        dc.SaveChanges();
    }
}

Теперь, если вам нужно запросить репозиторий, вы хотите сделать что-то вроде этого.
прости меня, приведенный ниже код не проверен, и я на самом деле больше похож на парня из VB: (
надеюсь, вы получитеточка

public class PersonsService
{
    private PersonRepository<Person> personRepository;

    public PersonService()
    {
        personRepository = new PersonRepository<Person>();
    }

    public UsablePerson GetPersonByID(int ID)
    {
        UsablePerson person = (from p in personRepository<Person>.Retrieve
                               where p.ID = ID
                               select new UsablePerson { p.FirstName, 
                                                         p.LastName, 
                                                         p.EmailAddress }).FirstOrDefault();

        return person;
    }
}

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

Отсюда «лично» у меня также есть Сервисный уровень, который имеет дело с нюансами подключения к данным ... такими вещами, как GetPersonByID или GetPeopleSince(DateTime marker). Именно здесь я убираю информацию, которую я не получаю.t (IE: пароли) и сохраните оставшуюся информацию либо в ViewModel, либо в другом POCO.

2 голосов
/ 23 февраля 2012

Если вы думаете о доменно-управляемом дизайне, тот факт, что один объект имеет другую конфигурацию, скорее всего, указывает на разные домены.Это не требует отдельного объекта для каждого, но это хороший шаблон.Один из способов добиться этого - иметь базовый класс с минимальным набором свойств.Затем вы создаете больше «предметно-ориентированных» классов, которые наследуются от базы.

Что касается возврата данных, существует множество способов «ограничения трафика» потока.Например, несколько репозиториев хорошо разделяют домены.Но это добавляет сложности (не очень хорошая идея, если в этом нет необходимости).Мне не нравится один репозиторий, возвращающий разные объекты.Это более приемлемо, если у вас есть некоторые обнуляемые свойства (возможно).

Мне не нравится LINQ to SQL как DAL, как предложил @KethiS, но я в основном работаю в Enterprise Environment и LINQ to SQLотстой в масштабе.Использование LINQ в противном случае это здорово.Просто мои два цента.

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

0 голосов
/ 11 апреля 2013

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

0 голосов
/ 23 февраля 2012

Мне нравятся репозитории на основе Linq для такого рода вещей. Linq2SQL, MSEF или Linq2NH позволят вам с помощью метода Select () определить список столбцов. Затем вы получите объект домена или класс сущностей, заполненный только тем, что вы указали. Вы можете иметь дополнительный код для сопоставления этого с DTO или просто использовать класс домена, зная, что он не был полностью «гидратированным».

...