Вы предпочитаете возвращать измененный объект или нет?

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

-- Description: Turns a query into a formatted HTML table. Useful for emails. 
-- Any ORDER BY clause needs to be passed in the separate ORDER BY parameter.
-- =============================================
CREATE PROC [dbo].[spQueryToHtmlTable] 
(
  @query nvarchar(MAX), --A query to turn into HTML format. It should not include an ORDER BY clause.
  @orderBy nvarchar(MAX) = NULL, --An optional ORDER BY clause. It should contain the words 'ORDER BY'.
  @html nvarchar(MAX) = NULL OUTPUT --The HTML output of the procedure.
)
AS
BEGIN   
  SET NOCOUNT ON;

  IF @orderBy IS NULL BEGIN
    SET @orderBy = ''  
  END

  SET @orderBy = REPLACE(@orderBy, '''', '''''');

  DECLARE @realQuery nvarchar(MAX) = '
    DECLARE @headerRow nvarchar(MAX);
    DECLARE @cols nvarchar(MAX);    

    SELECT * INTO #dynSql FROM (' + @query + ') sub;

    SELECT @cols = COALESCE(@cols + '', '''''''', '', '''') + ''['' + name + ''] AS ''''td''''''
    FROM tempdb.sys.columns 
    WHERE object_id = object_id(''tempdb..#dynSql'')
    ORDER BY column_id;

    SET @cols = ''SET @html = CAST(( SELECT '' + @cols + '' FROM #dynSql ' + @orderBy + ' FOR XML PATH(''''tr''''), ELEMENTS XSINIL) AS nvarchar(max))''    

    EXEC sys.sp_executesql @cols, N''@html nvarchar(MAX) OUTPUT'', @html=@html OUTPUT

    SELECT @headerRow = COALESCE(@headerRow + '''', '''') + '''' + name + '''' 
    FROM tempdb.sys.columns 
    WHERE object_id = object_id(''tempdb..#dynSql'')
    ORDER BY column_id;

    SET @headerRow = '''' + @headerRow + '''';

    SET @html = '''' + @headerRow + @html + ''
''; '; EXEC sys.sp_executesql @realQuery, N'@html nvarchar(MAX) OUTPUT', @html=@html OUTPUT END GO

Использование:

DECLARE @html nvarchar(MAX);
EXEC spQueryToHtmlTable @html = @html OUTPUT,  @query = N'SELECT * FROM dbo.People', @orderBy = N'ORDER BY FirstName';

EXEC msdb.dbo.sp_send_dbmail
    @profile_name = 'Foo',
    @recipients = 'bar@baz.com;',
    @subject = 'HTML email',
    @body = @html,
    @body_format = 'HTML',
    @query_no_truncate = 1,
    @attach_query_result_as_file = 0;

Связанный: Вот аналогичный код для преобразования любого произвольного запроса в строку CSV .

5
задан Schotime 3 June 2009 в 05:01
поделиться

6 ответов

Лично я предпочитаю разделение команд и запросов - т. Е. Методы, возвращающие результат, не должны быть мутаторами, и наоборот. Я понимаю аргументы в пользу того, что вернет эту толпу, то есть простоту «цепочки» вызовов:

foo.ChangeThis(23).ChangeThat(45).AndAlso(67);

но это '

6
ответ дан 13 December 2019 в 05:41
поделиться

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

Типичный случай возврата объекта методом рассматривается в шаблоне построителя , например, класс StringBuilder :

new StringBuilder("Hello").Append(" ").Append("World!").ToString();

Но в целом, если такое связывание методов не будет выполняться, я бы предпочел ничего не возвращать. Если распространенный вариант использования - не использовать возвращаемый объект (а просто отбросить его), это может показаться пустой тратой.

3
ответ дан 13 December 2019 в 05:41
поделиться

Самое интересное в том, чтобы сделать это первым способом, при котором вы фактически возвращаете элемент после его изменения, заключается в том, что он позволяет использовать цепочку методов. Это означает, что вы можете сделать что-то вроде этого:

c.ModifyIt("hello").MessWithIt("World").ReallyScrewWithIt("!!!");

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

myStringBuilder.Replace("!", "?").Append("Something").Remove(4,3);
2
ответ дан 13 December 2019 в 05:41
поделиться

Лично я предпочел бы создать такую ​​функцию, как ModifyIt, и поместить ее в создаваемый мной класс, если это возможно. Причина, по которой я говорю это, заключается в том, что в обоих методах я изменяю вызывающую переменную, потому что передаю ее по ссылке. Естественно, я не могу сделать это для всех функций, но включение ref в вызове функции помогает пояснить, что я передаю переменную по ссылке, а не по значению. Пример:

public Class ModifyIt(ref Class c)

Почему? Потому что, когда я возвращаюсь и читаю код, я могу забыть, что я передал значение по ссылке, и тогда я, скорее всего, сделаю что-то «плохое» с кодом.

1
ответ дан 13 December 2019 в 05:41
поделиться

Во-первых, если вы меняете только одно свойство, у меня вообще не было бы отдельной функции модификации; Я бы просто поменял собственность напрямую. Разобравшись с этим, давайте предположим, что вы даете простой пример чего-то более сложного, возможно, с несколькими различными изменениями внутри функции модификации.

Я бы использовал тот, который возвращает объект 'Class'. Это позволяет объединить несколько вызовов в цепочку. Опять же, я предполагаю, что это простой пример более сложной системы; предположим, что вместо этого у вас есть MakeModification (), MakeAnotherModification () и MakeAThirdModification (). Если вы вернете объект Class, вы получите следующую синтаксическую точность:

Class c = new Class();
c.MakeModification().MakeAnotherModification().MakeAThirdModification();
0
ответ дан 13 December 2019 в 05:41
поделиться

На самом деле я предпочитаю второй стиль, поскольку метод является мутатором, поэтому не ожидается возврата нового значения, вместо этого ожидается изменение фактического значения. Однако вам может потребоваться указать, что ModifyIt принимает переменную ref, чтобы указать, что фактический c будет изменен. c здесь передается по значению, хотя это ссылочный тип, все же существует разница между передачей ссылочных типов по значению и передачей ссылочных типов по ссылке. См. Следующее:

public void ModifyIt(Myclass c) { c = new MyClass(); } 

в приведенном выше случае переменная c будет передана по значению (т. Е. Копия из ссылки будет передана и изменена, чтобы указывать на новый экземпляр объекта, что, в свою очередь, означает, что у вас будет два объекта в данном случае введите MyClass. Вот пример для иллюстрации:

Myclass s = new MyClass () { prop = "value" }; ModifyIt(s); Console.WriteLine(s.prob); // this will print "value"

хотя MOdifyIT создал экземпляр ссылки на новый объект, что должно означать, что проблема будет инициализирована значением null, на самом деле он не создавал экземпляр s, он создавал экземпляр s. в отличие от случая, если s было передано ref.
Надеюсь это поможет!

0
ответ дан 13 December 2019 в 05:41
поделиться
Другие вопросы по тегам:

Похожие вопросы: