sexta-feira, 11 de abril de 2014

SQL Server - Busca de Índices

Realmente não é uma tarefa trivial a análise e busca de índices no banco de dados do SQL Server, devido ao simples fato da diversidade deles.

Por exemplo, veja algumas opções abaixo:
Tipo Descrição Informação Adicional
Clustered Um índice [agrupado] ordena e armazena as linhas de dados da tabela ou visão baseado em uma chave de índice agrupada. O índice agrupado é implementado como uma estrutura na qual os dados de uma tabela poderão ser retornados rapidamente. Clustered And Nonclustered Indexes
Nonclustered Um índice [não agrupado] pode ser definido em uma tabela ou visão com um índice agrupado ou em uma pilha. Cada linha de um índice contém um valor chave não agrupado e um localizador de linha. Este localizador aponta para a linha de dados em um índice agrupado ou pilha tendo o valor da chave. Clustered And Nonclustered Indexes
Unique Um índice único assegura que a chave de índice não contém valor duplicado, portanto cada linha na tabela ou visão é unica. Create Unique Indexes
Index with included columns Refere-se a um índice [não agrupado] que é extendido para incluir colunas [não chave] em adição as colunas chave. Create Indexes with Included Columns

Além de vários outros...

Para um desenvolvedor, ter que buscar estes tipos de índices programaticamente pode ser desafiador. Então, como uma dica, segue abaixo tipos diferentes de Queries para retornar tipos diferentes de índices.

Busca de Foreign Keys

SELECT f.name AS ForeignKey,  
      TableSchema =   
           (SELECT TOP 1 s.name FROM sys.schemas s JOIN sys.tables t ON t.schema_id = s.schema_id AND t.object_id = f.parent_object_id),  
   OBJECT_NAME(f.parent_object_id) AS TableName,  
   COL_NAME(fc.parent_object_id, fc.parent_column_id) AS ColumnName,  
   ReferenceTableSchema =   
           (SELECT TOP 1 s.name FROM sys.schemas s JOIN sys.tables t ON t.schema_id = s.schema_id AND t.object_id = f.referenced_object_id),  
      OBJECT_NAME (f.referenced_object_id) AS ReferenceTableName,  
   COL_NAME(fc.referenced_object_id, fc.referenced_column_id) AS ReferenceColumnName  
 FROM sys.foreign_keys AS f  
   INNER JOIN sys.foreign_key_columns AS fc ON f.OBJECT_ID = fc.constraint_object_id  



Busca de Primary Keys / Unique Key Constraints

 SELECT ROW_NUMBER() OVER (PARTITION BY k.name ORDER BY ic.key_ordinal, s.name, t.name, c.name) rowC,  
        s.name TABLE_SCHEMA, t.name TABLE_NAME,  
     k.name CONSTRAINT_NAME, K.type_desc CONSTRAINT_TYPE, c.name COLUMN_NAME,  
        ic.key_ordinal AS ORDINAL_POSITION  
 FROM sys.key_constraints k  
      JOIN sys.tables t ON t.object_id = k.parent_object_id  
      JOIN sys.schemas s ON s.schema_id = t.schema_id  
      JOIN sys.index_columns as ic ON ic.object_id = t.object_id  
      AND ic.index_id = k.unique_index_id  
      JOIN sys.columns as c ON c.object_id = t.object_id  
      AND c.column_id = ic.column_id  
 WHERE s.name <> 'dbo'  


Busca de [Unique Index]

 SELECT ROW_NUMBER() OVER (PARTITION BY i.name, s.name, o.name ORDER BY i.name, s.name, o.name, co.name) rowC,  
        i.name IndexName, s.name SchemaName, o.name TableName, co.name ColumnName, ic.key_ordinal ColumnOrder  
 FROM sys.indexes i   
 JOIN sys.objects o ON i.object_id = o.object_id  
 JOIN sys.index_columns ic ON ic.object_id = i.object_id   
    AND ic.index_id = i.index_id  
 JOIN sys.columns co ON co.object_id = i.object_id   
    AND co.column_id = ic.column_id  
 JOIN sys.tables t ON t.object_id = o.object_id  
 JOIN sys.schemas s ON s.schema_id = t.schema_id  
 WHERE i.[type] = 2   
 AND i.is_unique = 1   
 AND i.is_primary_key = 0  
 AND o.[type] = 'U'  


Busca de [Index Not Unique]

 SELECT ROW_NUMBER() OVER (PARTITION BY i.name, s.name, o.name ORDER BY i.name, s.name, o.name, ic.key_ordinal, co.name) rowC,  
        i.name IndexName, s.name SchemaName, o.name TableName, co.name ColumnName, ic.key_ordinal ColumnOrder  
 FROM sys.indexes i   
 JOIN sys.objects o ON i.object_id = o.object_id  
 JOIN sys.index_columns ic ON ic.object_id = i.object_id   
    AND ic.index_id = i.index_id  
 JOIN sys.columns co ON co.object_id = i.object_id   
    AND co.column_id = ic.column_id  
 JOIN sys.tables t ON t.object_id = o.object_id  
 JOIN sys.schemas s ON s.schema_id = t.schema_id  
 WHERE i.is_unique = 0   
 AND i.is_primary_key = 0


Busca de [Default Constraints]

 SELECT s.name SchemaName, t.name TableName, col_name(df.parent_object_id, df.parent_column_id) ColumnName, df.*  
 FROM sys.default_constraints df  
       JOIN sys.tables t ON df.parent_object_id = t.object_id  
       JOIN sys.schemas s ON t.schema_id = s.schema_id  


That's It!!

quinta-feira, 13 de março de 2014

Windows Phone - Notification Manager

Utilize de forma mais eficiente o [serviço de agente] do Windows Phone, habilitando os seguintes recursos com a aplicação [GT Phone Notifier]:

- Cadê meu ônibus (disponível somente para a cidade de São Paulo - Brasil) - Você pode rastrear seu ônibus de forma rápida e prática. Inclusive acompanhar no mapa sua movimentação, ao vivo.

- SMS + Alarme - Use este recurso para ser avisado de uma data importante com a vantagem de enviar um SMS pré-cadastrado para este momento.

- Quando seu WiFi estiver ligado por mais de 30 minutos e sem conexão com alguma rede a aplicação lhe sugere para desligar, com link para a tela de configuração WiFi nativa do Windows Phone

- A cada 30 minutos o aplicativo guarda sua posição geográfica e se você está usando uma conexão WiFi no local. Ao passar novamente pelo local armazenado o aplicativo pode avisá-lo se deseja ligar seu WiFi, com link para a tela de configuração WiFi nativa do Windows Phone

- Gerenciador de Lembretes - Você pode configurar lembretes de acordo com sua posição geográfica (e de acordo com a previsão do tempo também). Desta forma, toda vez que passar por um determinado local o aplicativo pode lhe avisar algo como por exemplo um compromisso naquele local.

- Calendário nativo de compromissos - Você pode habilitar o sistema para ler e lhe avisar sobre seus futuros compromissos na região em que está passando no momento. Desta forma não esquecerá mais deles! rsrs

- AirPlane Mode - Habilitar/Desabilitar AirPlane Mode quando se aproximar de um aeroporto

- Compartilhe sua localização com seus amigos. A aplicação se integra ao Microsoft [OneDrive] para enviar sua localização (ou qualquer outra) para sua pasta [Pública] no OneDrive. Se você compartilhar (no OneDrive) o arquivo enviado pela aplicação - GT.Phone.Notifier.User.Location.xml - com algum contato seu, este contato poderá visualizar sua localização dentro da aplicação.

- Use a voz para interagir com o aplicativo:

Dizendo "GT Phone..."
"Adicionar Lembrete" - o sistema abre a tela de cadastro de lembretes
Dizendo "GT Phone..."
"Mostrar Último Lembrete" - o sistema abre a tela de lembretes, mostrando o último lembrete que você visualizou
Dizendo "GT Phone..."
"Falar Último Lembrete" - o sistema abre a tela de lembretes, mostrando e [falando] o último lembrete que você visualizou

Segue algumas telas do aplicativo e link para compra na Windows Phone Store:

P.S.: Por favor, não deixem de testar e dar sugestões para melhorar a aplicação ainda mais! :-)
Na seção [about] da aplicação você pode classificar e dar sua sugestão, clicando no botão [classifique esta aplicação].



-------------------------------------------------------------------------------------------

- Where's my bus (available only for the city of Sao Paulo - Brazil) - You can track your bus quickly and conveniently. You can also follow the movement of buses on the map - live.

- SMS + Alarm - Use this feature to be notified about an important date with the advantage of sending a personalized SMS just for this moment.

- When your WiFi is enabled for more than 30 minutes with no connection to a network, GT Phone Notifier will prompt you to disable it. 

- Every 30 minutes the application saves its geographical position and if you are using a WiFi connection on site. To bypass the stored location the application can warn you if you want to connect your WiFi with a link to the native WiFi setup screen of Windows Phone

- Manager Reminders - You can set reminders according to their geographical position (and weather forecast). Thus , every time you pass by a certain location , the application can warn you something , such as a commitment that location .

- Native Calendar appointments - You can enable the system to view , and warn you about your upcoming appointments in the region that is experiencing at the moment. Thus most of them will not forget !  :-)

- AirPlane Mode - Enable/Disable AirPlane Mode when approaching an airport

- Share your location with your friends. The application integrates with Microsoft [OneDrive] to send your location (or any other) to your [Public] folder on OneDrive. If you share 
(in OneDrive) the file sent by the application - GT.Phone.Notifier.User.Location.xml - for some contact, this contact can view your location within the application. 

- Use your voice to interact with the application :
Saying " GT Phone ... "
"Add Reminder" - the system opens the registration screen reminders
Saying " GT Phone ... "
"Show Last Reminder" - the system opens the Reminders screen , showing the last reminder that you viewed
Saying " GT Phone ... "
"Speak Last Reminder" - the system displays a screen reminders , and showing [speaking ] the last reminder that you viewed

Here are a few screens of the application and link to purchase the Windows Phone Store:

PS : Please do not forget to test and give suggestions to improve the application further ! :-)
In [ about ] section of the application you can sort and give your suggestion by clicking the [ classify this application ] .





quinta-feira, 23 de janeiro de 2014

Dica - Deploy WCF - HTTPS Environment

Geralmente quando desenvolvemos nosso WCF, e testamos localmente, ficamos felizes ao vê-lo executar com sucesso. Porém, um pequeno pesadelo pode ocorrer quando implantamos nosso serviço em um servidor do nosso cliente e erros estranhos começam a acontecer. Por exemplo, se o seu cliente instalou um certificado de segurança no IIS deste servidor (serviço SSL), as coisas podem ficar complicadas para nós. E como nosso serviço é por padrão criado no modelo HTTP, e não HTTPS, geralmente vamos nos deparar com a seguinte mensagem

Could not find a base address that matches scheme https for the endpoint with binding WebHttpBinding. Registered base address schemes are [http].

Nestes casos, uma dica rápida seria simplesmente [desabilitar] o modo de segurança do Binding usado no seu Endpoint.

Ao abrir seu Web.config padrão, gerado pelo Visual Studio, procure pela frase [security mode=] e altere para a sugerida abaixo. Inclusive, como outra dica, para funcionar a execução do seu WCF via execução JavaScript, use o Bind do tipo [webHttp].


<webHttpBinding> 
<binding crossDomainScriptAccessEnabled="true" name="webBinding"> 
<security mode="None">        
<transport clientCredentialType="None">
</transport>
</security> 
</binding> 
</webHttpBinding>


E se você estiver executando seu WCF em um servidor sem certificado (sem SSL) poderá verficar um exemplo completo neste Artigo.

Desta forma seu serviço vai ser executado com sucesso e o dia será ganho!... :)
[]s

Fontes: webHttpBinding

terça-feira, 7 de janeiro de 2014

What's New ASP.NET MVC 5

Embarcado no novo Visual Studio 2013 temos algumas novidades no desenvolvimento Web.
Por exemplo, agora existe apenas uma interface para criação de projetos Web, que oferece suporte para os múltiplos frameworks ASP.NET (Web Forms, MVC e Web API).

Desta forma, quando clicamos em [Novo Projeto] no Visual Studio, notamos no painel a esquerda apenas um template chamado [ASP.NET Web Application]



Ao clicar em Ok, aparecerá os diversos frameworks para desenvolvimento ASP.NET



Inclusive podemos adicionar suporte de um tipo de framework em outro. Por exemplo, ao criar um projeto do tipo [Web Forms] podemos adicionar alguns recursos do framework MVC ou Web API





E se quisermos alterar o método de autenticação de nossa aplicação, existe agora um botão chamado [Change Authentication]





Notou novidades nas formas de autenticação? Vamos a elas:


1 - No Authentication
Selecionando esta opção a sua aplicação não conterá qualquer página para autenticação de usuários, nenhuma tela indicando quem entrou no sistema ou qualquer classe de entidade em apoio ao conjunto de membros (membership) ou [connection string] com o banco de dados. 

2 - Individual User Accounts
Com esta opção sua aplicação será configurada para usar o recurso ASP.NET Identity (formalmente conhecida como ASP.NET membership). Desta forma poderemos criar um novo usuário/senha pela aplicação ou autenticar o usuário usando um provedor externo como Google, Facebook, Microsoft Account ou Twitter. Semelhante ao anterior ASP.NET membership, os dados dos usuários ficarão armazenados em um banco de dados local (localDB).

3 - Organizational Accounts
Finalmente temos uma forma nativa de acesso a biblioteca [WIF - Windows Identity Foundation] para autenticação baseada em usuários do AD - Active Directory da empresa ou WAAD - Windows Azure Active Directory.

[WAAD]


[AD]


Não entraremos em detalhes sobre este tipo de autenticação neste momento pois ele merece um novo artigo! :-)

4 - Windows Authentication
Com esta opção sua aplicação usará o módulo de autenticação por IIS do Windows. A aplicação mostrará o ID do domínio/usuário do AD ou da conta do usuário que entrou no Windows. Use esta opção para criar aplicações que rodarão na sua [intranet] somente.

Já que estamos falando em autenticação, vamos treinar uma forma de autenticação externa, no Google, em ASP.NET MVC 5!

Abra o Visual Studio 2013 (ou Express) e clique em Novo Projeto, Visual C# -> Web -> e na opção ASP.NET Web Application





Agora rode a aplicação (F5) e note que existe uma novidade, um painel de navegação flutuante para as opções de menu padrão da aplicação (este opção aparece dependendo do tamanho do seu Browser)





Vamos agora habilitar o recurso para autenticação pelo provedor - Google OpenID

Abra o arquivo [App_Start\Startup.Auth.cs] e habilite a linha [app.UseGoogleAuthentication()].



Pressione F5 para iniciar a aplicação e clique no Link [Log In]. Note que na parte final da tela vai aparecer um botão para conexão com seu usuário do Google





A partir de agora basta efetuar o login no provedor do Google e aceitar o termo de condição para que sua aplicação visualize informações básicas do usuário do Google.









Bootstrap in the Visual Studio 2013
O template de projeto MVC foi atualizado para usar Bootstrap de forma a prover um design mais produtivo, responsivo e mais fácil de customizar.

Por exemplo, quando criamos um novo projeto ASP.NET MVC 5, ao rodar a aplicação você vai notar que o design se adapta bem a diferentes tamanhos de janela do navegador.

Ao Iniciar a aplicação



Com a janela mais estreita, note que as informações do site se movem para o centro do browser



Estreite um pouco mais e o menu se adapta e se transforma



E para alterar este stilo padrão do Visual Studio basta incluir um novo CSS no seu projeto - por exemplo, buscando temas no site http://bootswatch.com - e referenciar este novo css no arquivo [App_Start/Bundle.config] do projeto





Attribute routing

ASP.NET MVC agora suporta atributos de roteamento, ou seja, você especifica suas rotas como anotações nas suas classes de controle e nas [actions] da classe.

Para começar a usar este recurso instale-o via nuget package, através do comando [Install-Package AttributeRouting]:



Com isto será criada a classe [~/App_Start/AttributeRouting.cs/vb] no seu projeto. Já podemos então trabalhar com este novo recurso.

De forma limitada nós já trabalhamos com roteamento de atributos, sendo eles: GET, POST, PUT e DELETE. Com o apoio deste novo recurso podemos estender e muito esta funcionalidade.
O interessante é que isto é uma contribuição adotada pela Microsoft e o contribuidor se chama Tim McCall.

A explicação completa deste importante recurso MVC pode ser encontrada em http://attributerouting.net.

Fontes:
ASP.NET and Web Tools for Visual Studio 2013 Release Notes
Create an ASP.NET MVC 5 App with Facebook and Google OAuth2 and OpenID Sign-on (C#)
Creating ASP.NET Web Projects in Visual Studio 2013

terça-feira, 26 de novembro de 2013

Reporting Services - Matrix - Largura das Colunas Dinâmicas


Apesar da flexibilidade do componente Matrix, sempre nós, desenvolvedores - ou o usuário final - vamos solicitar algo que este ou algum componente não vai atender!!

Mas graças a criatividade humana (use com moderação :) ) podemos pelo menos chegar a um resultado satisfatório, pois já que não é possível configurar a largura de cada coluna que será criada, vamos adicionar um artifício para, hora mostrar ou não uma coluna adicional, criada ao lado da coluna na Matrix. Usei como "inspiração" a idéia registrada no blog do Leigh Waldie.

Então, vamos imaginar que a Matrix irá criar várias colunas, infelizmente todas com a mesma largura. Para deixar isto um pouco melhor, vamos criar um recurso para mostrar as colunas "com larguras diferentes".

Primeiro, vamos adicionar a coluna auxiliar, do lado direito da única coluna do objeto Matrix, e dentro do grupo já existente desta coluna genérica (Inside Group - Right) , como ilustrado abaixo:



Agora o truque consiste em "ligarmos" o modo avançado para edição das propriedades da [Column Groups] do relatório, visualizar a [segunda] propriedade "Static" - segunda, pois se refere a coluna auxiliar que estamos manipulando - e finalmente adicionar a expressão desejada no atributo [Hidden]. No meu caso, quero somente habilitar a Coluna Auxiliar se o [valor] da Matrix tiver um comprimento maior ou igual a 10, conforme ilustrado:



Não esqueça de efetuar um [merge] das colunas do seu [Data Region] para uma visualização correta dos dados, já que você agora possui uma coluna auxiliar que aparece/desaparece.



E como resultado final, note que somente para colunas com conteúdo [menor ou igual a 10] não temos o "apoio" da Coluna Auxiliar (no caso, as colunas [Revisão] e [Data de Recebimento]), como ilustrado abaixo:



[]s

segunda-feira, 11 de novembro de 2013

Windows Phone - ListBox [UnSelectAll]


Podemos facilmente selecionar programaticamente todos os itens de um ListBox [múltipla escolha] através do método [SelectAll] porém, para a plataforma WP, não existe o método [UnSelectAll]. Sendo assim, vamos criar um!...
Vamos desde o início criar nosso projeto no Visual Studio para isto, conforme ilustrado abaixo:





Com o projeto inicial criado, substitua o conteúdo do [Code-Behind - MainPage.xaml.cs] pelo que segue:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using PhoneApp.Resources;

namespace PhoneApp
{
    public partial class MainPage : PhoneApplicationPage
    {
        // Constructor
        public MainPage()
        {
            InitializeComponent();
            this.MultiResultList.Items.Add("Item 1");
            this.MultiResultList.Items.Add("Item 2");
            this.MultiResultList.Items.Add("Item 3");
            this.MultiResultList.Items.Add("Item 4");
            this.MultiResultList.Items.Add("Item 5");
        }

        private void chkSelectAll_Click(object sender, RoutedEventArgs e)
        {
            var chk = (CheckBox)sender;

            if (chk.IsChecked.Value)
                this.MultiResultList.SelectAll();
            else
            {
                for (int i = this.MultiResultList.SelectedItems.Count - 1; i >= 0; i--)
                {
                    this.MultiResultList.SelectedItems[i] = null;
                }
            }
        }
    }
}


E também substitua seu XAML (MainPage.xaml) com o que segue:


<phone:PhoneApplicationPage
    x:Class="PhoneApp.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">

    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock Text="MY APPLICATION" Style="{StaticResource PhoneTextNormalStyle}" Margin="12,0"/>
            <TextBlock Text="page name" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>

        <!--ContentPanel - place additional content here-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">

            <ScrollViewer  BorderThickness="1">
                <StackPanel Margin="0,0,0,17" Width="432">

                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition />
                            <RowDefinition />
                        </Grid.RowDefinitions>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="432" />
                        </Grid.ColumnDefinitions>

                        <CheckBox Name="chkSelectAll" Grid.Row="0" Foreground="{StaticResource PhoneForegroundBrush}" Click="chkSelectAll_Click" >
                            <TextBlock Text="Selecionar Todos" TextWrapping="Wrap">
                            </TextBlock>
                        </CheckBox>

                        <ListBox Grid.Row="1"
                            Name="MultiResultList" 
                            SelectionMode="Multiple" 
                            Height="510" 
                            Margin="0,0,0,-510"
                            FontSize="{StaticResource PhoneFontSizeExtraLarge}">
                        </ListBox>

                    </Grid>

                </StackPanel>
            </ScrollViewer>
            

        </Grid>

    </Grid>

</phone:PhoneApplicationPage>


E verá que, ao clicar no CheckBox, todos os itens da lista serão marcados / desmarcados. O ponto importante a notar no code-behind é o loop reverso feito para desmarcar cada opção selecionada do ListBox


for (int i = this.MultiResultList.SelectedItems.Count - 1; i >= 0; i--)
{
    this.MultiResultList.SelectedItems[i] = null;
}


   

[]s!

quinta-feira, 12 de setembro de 2013

Team Foundation Server Express 2012 - Parte 3/3

Nesta terceira parte daremos continuidade em nossa configuração básica para gerenciamento do nosso restaurante PacktDiner.

Criando o Product Backlog Items (PBIs)
A gerente Meeta quer que nos foquemos em dois PBIs, nomeados [Place Order] e [Calculate Bill]. Isto vai permitir ao garçom efetuar o pedido, usando o histórico de pedidos do usuário e calcular a conta mais tarde, usando o histórico do cálculo de conta do usuário.


Novamente no portal Web Access do TFS (acessado através do Team Explorer do Visual Studio), na área Home do portal, clique no botão [Product Backlog Item]



Preencha a tela conforme exemplificado abaixo



Crie outro PBI, chamado Calculate Bill



Associando PBI x Sprint
Deveremos agora associar um item de trabalho (o primeiro PBI para desenvolvimento) no primeiro Sprint. Para isto, no portal, clique no link [Work]



Expanda a opção [Shared Queries] e clique em [Product Backlog].



Neste ponto você pode visualizar os dois PBIs na lista da direita. Clique com o botão direito no PBI [Place Order] e mova a iteração para o Sprint Corrente (1-1)



Salve as alterações



Se você se deparar com o erro da tela abaixo (TF51011) você terá que manualmente alterar todas as referências ao Sprint com o nome errado, alterando corretamente, salvando e rodando a query para resolver este "bug" do produto, conforme exemplifica a tela abaixo. Não se esqueça de alterar em todos os itens (dentro de Shared Queries -> Current Sprint)



Criando Sub-Tarefas
Cada PBI deve ser desmembrado em tarefas, pois os desenvolvedores irão trabalhar com tarefas. Para isto, acesse a opção [New -> Task] da área [Work] do portal



E cadastre uma nova tarefa para a [Sprint 1-1] da forma mostrada abaixo



Salve e crie mais duas, com os mesmos dados, mas com os nomes [Implement Business Logic] e [Implement Storage Service]
Após estes passos crie outra tarefa chamada [Add test cases] com o campo Activity como [Requirements].



Configurando a estrutura Source Control
Isto se faz no Visual Studio. Voltando ao Team Explorer, selecione a opção Home, depois o link [Source Control Explorer] abaixo do nó [Pending Changes].



Precisamos associar nossa estrutura de fontes a um diretório físico em nossa máquina. Clique no link [Not mapped] para isto, e associe a um diretório de sua escolha (por exemplo d:\projetos\PacktDiner)



Clicando no botão [Map] você receberá a pergunta abaixo. Responda [Não] a esta pergunta



Agora sim clique no botão [New Folder]. Crie a estrutura exatamente como ilustrado abaixo



Depois clique em Pending Changes, no Team Explorer





Agora realize o Check In, adicionando um comentário, por exemplo, "pastas adicionadas" e clique no botão [Check In]



Criando a aplicação WaiterApp no Visual Studio
Até o momento criamos a estrutura da aplicação no TFS e o mapeamento em um diretório físico na nossa máquina (no meu caso D:\Projetos\PacktDiner\WaiterApp\main). Porém este diretório está vazio certo. Não existe uma aplicação lá dentro. Vamos rapidamente criar, usando o Template do Visual Studio para aplicações ASP.NET MVC, por exemplo.

No Visual Studio escolha a opção de Menu File -> New -> Project. Note na imagem abaixo que devemos criar o projeto dentro da pasta [src].






Pronto. Não vamos, é claro, criar telas e regras de negócio para atender a aplicação do restautante, pois o objetivo deste artigo é controlar a aplicação no TFS.

Agora precisamos adicionar todos os arquivos criados na pasta [src] ao TFS, pelo Visual Studio. Na janela [Source Control Explorer] pressione [Add Files to Source Control]







Na janela Team Explorer, sob a aba Home, Pressione o link Pending Changes e adicione um comentário apropriado (Waiter App adicionada, por exemplo) e clique no botão Check In.

E como passo final, feche a solução, dê duplo clique no nome da solução [WaiterApp.sln] no Source Control Explorer e crie o link da sua solução no Source Control.

Clique Sim



Selecione uma linha por vez e clique no botão [bind] para criar a conexão



Clique em Check Out para começar a trabalhar nos arquivos



Instalando e configurando o sistema de BUILD
Falta agora apontar nossa aplicação a um processo automático de Build. Normalmente se aponta o projeto para um servidor separado de Build. Mas para nosso tutorial criaremos este processo no mesmo servidor do TFS.
Para isto, inicie novamente o [Setup] de instalação do TFS (VS2012.3 TFS Express enu.iso).



Escolha a opção [Configure Team Foundation Build Service]





Botão Next



Botão Next











Integração contínua de BUILD
Vamos trabalhar agora com este processo de Build no Visual Studio. Entre no [Team Explorer - Build]



Clique em [New Build Definition] e preencha de acordo com as telas de exemplo





Para a configuração de [Source Settings] altere esta aba exatamente conforme mostrado abaixo



No próximo passo (Build Defaults) crie na sua máquina um diretório chamado [Drops]



Torne este diretório [compartilhado]





Atente para o fato de que a conta a qual o serviço de build está rodando possua permissão na pasta Drops (conta [Network Service]). Adicione o caminho do diretório compartilhado no campo [Stating Location]



E por último, o Process Build



Salve a definição de Build



Botão direito no Build criado e escolha [Queue a new build]





Pronto. Agora faça uma alteração em algum arquivo, depois efetue o Check-In, o qual será levado para a aba de Pending Changes. Adicione um comentário e conclua o Check-In. Vá para a aba Builds e note que um novo Build foi inicialdo automaticamente. Após um pequeno processo de espera, o processo termina (muda para verde) indicando um Build bem sucedido.





E eis que surge no diretório Drops sua aplicação automaticamente compilada e pronta para ser implantada em produção!