использование индексатора для извлечения объекта Linq to SQL из хранилища данных - PullRequest
2 голосов
/ 15 апреля 2010
class UserDatastore : IUserDatastore
{
    ...

    public IUser this[Guid userId]
    {
        get
        {
            User user = (from u in _dataContext.Users
                             where u.Id == userId
                             select u).FirstOrDefault();

            return user;
        }
    }

    ...
}

Один из разработчиков в нашей команде утверждает, что индексатор в вышеуказанной ситуации не подходит и что метод GetUser(Guid id) должен быть предпочтительным.

Аргументы таковы:

1) Мы не индексируем коллекцию в памяти, индексатор в основном выполняет скрытый запрос SQL 2) Использование Guid в индексаторе плохо (это также помечено FxCop) 3) Возврат null из индексатора не нормальное поведение 4) Пользователь API обычно не ожидал бы такого поведения

Я согласен в определенной степени с (большинством) из этих пунктов.

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

Кроме того, учитывая, что это унаследованная кодовая база, которая широко и последовательно использует этот шаблон, стоит ли рефакторинг? Я согласен с тем, что, возможно, было бы лучше использовать метод Get с самого начала, но я еще не уверен, что использование индексатора совершенно неправильно.

Мне было бы интересно услышать все мнения, спасибо.

Ответы [ 2 ]

0 голосов
/ 15 апреля 2010

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

Лично я считаю, что свойства и индексаторы не должны скрывать длинные выполняющиеся операции, хотя LINQ-to-SQL может кэшировать Users. Вот почему я бы тоже предпочел метод.

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

0 голосов
/ 15 апреля 2010

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

Возвращение null довольно редко, как обычно с индексатором, если индекс (ключ) отсутствует в коллекции, вместо этого вы бы выдавали исключение.

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

public IUser this[Guid userId]
{
    get { return GetUser(userId); }
}

private IUser GetUser(Guid userId)
{
    return (from u in _dataContext.Users 
            where u.Id == userId 
            select u).FirstOrDefault();
}

С точки зрения дизайна, лично я не использовал бы индексатор, я бы использовал метод GetUser.

...