Возможные способы вернуть подмножество данных из репозитория <T>? - PullRequest
3 голосов
/ 22 сентября 2009

Допустим, мне нужно отобразить список клиентов, но я хочу только отобразить имя и каким-то образом связать ключ с именем в элементе управления списком.

Вероятно, было бы дорого получить весь список клиентов и все его свойства. В этом случае было бы лучше создать другой класс со свойствами, которые требуются (в данном случае Id и Name)?

Базовая реализация может выглядеть так:

public class Customer {
    public int Id { get; set; }
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public int Age { get; set; }
    .....
}

public class CustomerListView {
    public int Id { get; set; }
    public string Name { get; set; }
}

public interface IRepository<T> {
    public T Find(int id);
    public IEnumerable<T> FindAll();
    ....
}

public class Repository<T>: IRepository<T> {
    ....
}

public class CustomerRepository: Repository<Customer> {
    public IEnumerable<CustomerListView> FindAllListView();
}

Подойдет ли этот подход? Какие еще варианты будут?

Ответы [ 4 ]

2 голосов
/ 22 сентября 2009

Для достижения этих целей я создаю простой класс View, например CustomerView, который содержит только свойства, необходимые для отображения обзора.

Мой репозиторий затем имеет метод, который возвращает коллекцию этих объектов CustomerView.

Я в основном использую NHibernate в своих проектах. Nhibernate позволяет использовать «проекции». Итак, что я делаю в своем хранилище: (обратите внимание, что приведенный ниже код является просто псевдокодом; он не будет компилироваться).

public IList<CustomerView> GetAllCustomers()
{
    ICriteria crit = _session.CreateCriteria (typeof(Customer));

    crit.AddProjection ( ... );

    crit.SetResultTransformer (new EntityToBeanTransformer(typeof(CustomerView));

    return crit.ToList();
}

На самом деле все сводится к следующему: я говорю своему мапперу O / R, что он должен запрашивать клиентов, но он должен возвращать сущности типа 'CustomerView'. В определении проекции я также определяю, какие свойства класса Customer соответствуют каким свойствам класса CustomerView. Затем модуль O / R достаточно умен, чтобы сгенерировать очень простой запрос, который извлекает только те поля, которые необходимы для заполнения класса CustomerView. Например, выполняемый запрос может быть таким простым:

SELECT customerid, customername FROM tblCustomer
1 голос
/ 22 сентября 2009

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

Если список Клиентов уже существует в памяти, то там экономия отсутствует.

1 голос
/ 22 сентября 2009

Если вы используете IQueryable в качестве возврата вместо IEnumerable, то это не требует затрат:

CustomerRepository (). GetAll (). Find (1), потому что AsQueryable фактически не выполняется, пока вы не запросите данные. Это означает, что LINQ может оптимизировать его до:

ВЫБРАТЬ .... ОТ .... ГДЕ ID = 1 вместо

ПОЛУЧИТЕ ВСЕ. НАЙТИ ГДЕ ID = 1

См. Этот пост для объяснения:

Зачем использовать AsQueryable () вместо List ()?

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

0 голосов
/ 23 сентября 2009

Вы можете комбинировать методы, используемые Nissan и Frederik (анонимные типы и NHibernate), используя Linq-to-NHibernate.

Пункт № 31 в «Более эффективном» C # Билла Вагнера гласит «ограничить область действия типов с помощью анонимных типов», и я согласен. Кстати, я рекомендую всю книгу.

...