2009-08-11 4 views
2

У меня есть метод в моей DAL, возвращающий список клиентов:отложенной загрузки в моем C# приложении

Collection<Customer> FindAllCustomers(); 

Клиента имеет следующие столбцы: идентификатор, имя, адрес, Bio

мне нужно показать их в сетке с подкачками в моей ASPX-форме (show-customers.aspx), где я буду показывать только эти столбцы: ID, имя

Теперь, в моем DAL FindAllCustomers(), я также возвращаю поле Bio из SP (я заполняю коллекцию с помощью читателя)? Поле Bio может быть большим (nvarchar (max)). Я думал о ленивой загрузке или загрузке только необходимых полей. Но тогда в этом случае мне нужно будет создать еще один метод, который возвращает «полный» список клиентов, включая биографию, чтобы сторонние приложения могли использовать ее через сервисный уровень. Так это нормально, чтобы создать метод, как это:

Collection<Customer> FindAllCustomers(bool loadPartial); 

Если loadPartial = верно, то не загружать Bio, иначе загрузить его. В этом случае, поскольку я не хочу возвращать Bio из SP, мне нужно будет создать 2 оператора select в моем SP на основе значения bool.

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

Любые предложения по наилучшему образцу для реализации в таких случаях?

спасибо,

Викас

ответ

1

Если список клиентов никогда не показывает био~d, то с обтекаемой версией будет в порядке.

Несколько вопросов ...

  • ли этот параметр только определить, загружен ли Bio? В будущем у вас будут другие поля, которые не загружаются, если для них установлено значение true?
  • Что произойдет, если я попытаюсь получить доступ к Bio, если loadPartial был установлен в true?

Ключ будет гарантировать, что любой механизм, который вы выберете, будет устойчивым к изменению. Поставьте себя в сторону третьего лица и постарайтесь сделать ваши методы такими, как вы ожидали. Вы не хотите, чтобы разработчики, которые используют ваши классы, должны были глубоко понимать механизмы. Поэтому, возможно, вместо параметра «loadPartial» у вас просто есть другой метод, который разрешает быструю, минимальную информацию, необходимую для привязки к списку, и ленивые загружает другие поля по мере необходимости.

+0

1. Параметр bool, переданный в DAL, определяет, нужно ли нам загружать другие «несущественные большие» поля или нет. В будущем могут быть другие поля, которые могут не потребоваться. 2. Если loadPartial = true, био не будет вообще доступна. Я понимаю альтернативный способ: лениво загружать Bio, как только это свойство будет доступно. – user154624

+0

Но опять же, IMO для этого типа ленивой загрузки есть два метода: 1. в DAL читайте читатель в колонке Bio, но не загружайте его в свойстве Customer. В этом случае, поскольку читатель считывает всю строку (а не по столбцам), мы будем тратить драгоценную рассылку пропускной способности DB, позволяя SP возвращать весь столбец Bio для каждой записи. 2. Загрузите биоколонку через параметризованный SP, как только доступ к ресурсу Bio. В этом случае я бы сделал два звонка DAL. Не знаете, насколько это хорошо? – user154624

1

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

В качестве дополнительной заметки вам не обязательно нужны две хранимые процедуры или классическая инструкция if в хранимой процедуре.

Вы можете использовать оператор case, чтобы NULL вне поля, когда loadPartial == true.

Case WHEN @loadPartial = 1 THEN NULL ELSE [bio] END 
1

Я думаю, что это хорошо, если у вас есть два метода, оптимизированных для конкретных случаев, пока вы даете понять свои имена методов.Лично я не думаю:

Collection<Customer> FindAllCustomers(bool loadPartial); 

Очень ясно. Как разработчик знал бы, что на самом деле означает этот логический парам? См. Вопрос boolean parameters — do they smell?.

Дайте понять, и все в порядке.

3

Третья сторона - это связка.

На первый взгляд, я бы предположил, что вы обычно загружаете только минимальные данные, а затем загружаете полную или дополнительную информацию по запросам (т. Е. Прикосновение к свойству может вызвать вызов БД - возможно, незначительное злоупотребление собственностью) или в зависимости от характера того, что вы делаете.

Ленивый код недвижимости путем осветления:

class Customer 
{ 
    private string _lazydata = null; 

    public string LazyData 
    { 
    get 
    { 
     if (this._lazydata==null) 
     { 
     LazyPopulate(); 
     } 
     return this._lazydata; 
    } 
    } 

    private void LazyPopulate() 
    { 
    /* fetch data and set lazy fields */ 
    } 
} 

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

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

я бы с:

Collection<Customer> FindAllCustomers() 
{ 
    return this.FindAllCustomers(false); 
} 

Collection<Customer> FindAllCustomers(bool alldata) 
{ 
    /* do work */ 
} 
1

Почему бы не использовать отложенную загрузку в свойствах самого клиента класса? Дайте каждому свойству (Id, Name, Bio) частную переменную. В getter каждого свойства, если приватная переменная не равна null, верните ее, иначе прочитайте ее в своем DAL.

Когда дело доходит до Bio, если вам нужно лениво загрузить его, то в вашем получателе вы вызываете другой метод в классе клиентов LazyLoadAdditionalDetails() и вызываете соответствующие sprocs там, а затем возвращаете свою приватную переменную.

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

+0

Следует обратить внимание на этот подход в веб-среде. Использование подхода LazyLoad для отдельных свойств объекта Customer имеет недостаток, который в случае списка приведет к появлению нескольких запросов БД, которые могут быть запущены последовательно. В таком случае LazyLoading должен быть включен для списка в целом, скажем, для количества объектов, отображаемых на одной странице (если в списке используется пейджинг), что приведет к одному доступу к БД. – Juri

+0

Это может быть один запрос не сгусток, но он определенно требует ухода – annakata

+0

@annakata: Согласен. Некоторые из моих товарищей по работе попробовали это на прежнем проекте, где они сказали, что по этой причине это не сработало. Я думаю, они не пытались реализовать ленивую загрузку во всем списке, так как это было бы более реалистичным, я думаю (или реализую какое-то кэширование). – Juri

0
class CustomerDAO 
{ 
    private bool _LoadPartial = true; 
    public bool LoadPartial 
    { 
     get 
     { 
     return _LoadPartial; 
     } 

     set 
     { 
     _LoadPartial = value; 
     } 
    } 


    public Collection<Customer> FindAllCustomers() 
    { 
     ... 
    } 
} 

Был бы еще один вариант, хотя мне также понравился annakata.

0

Вместо

Collection<Customer> FindAllCustomers(bool loadPartial); 

Я бы сделать это

Collection<Customer> FindAllCustomers(bool includeBio); 

"loadPartial" не говорит потребителю, что представляет собой "частичную" клиента. Я также согласен с точками аннаката.

3

В этом случае я бы использовал перечисление, чтобы быть еще более понятным о значении параметра.

public enum RetrieveCustomerInfo 
{ 
    WithBio, 
    WithoutBio 
} 

И при вызове метода:

dao.FindAllCustomers(RetrieveCustomerInfo.WithBio); 

Я не знаю, если это лучше, но я думаю, что это более понятно.