Partilhar via


Como conectar seu aplicativo de código ao SQL do Azure (versão prévia)

Este guia explica como configurar um Banco de Dados SQL do Azure e conectá-lo a um aplicativo de código do Power Apps usando o Power SDK.

Observação

As versões prévias dos recursos não foram criadas para uso em ambientes de produção e podem ter funcionalidade restrita. Esses recursos estão disponíveis antes de um lançamento oficial para que os clientes possam obter acesso antecipado e fornecer comentários.

Este guia aborda:

  • Provisionando um SQL Server e um banco de dados do Azure
  • Criando tabelas SQL e procedimentos armazenados
  • Conectando um aplicativo de código do Power Apps usando o SDK do Power

Pré-requisitos

Configurar o SQL Server e o Banco de Dados do Azure

  1. Navegar até selecionar a opção de implantação do SQL – Microsoft Azure
  2. Selecionar banco de dados SQL –> Tipo de recurso: banco de dados único ->Criar
  3. Preencher:
    • Grupo de recursos: selecione Criar novo e insira um nome de grupo de recursos, por exemplo, rg-codeapps-dev
    • Nome do banco de dados: sqldb-codeapps-dev
    • Servidor: Selecione Criar novo e Preencher:
      • Nome do servidor: sql-codeapps-dev
      • Local: selecione a região mais próxima do seu ambiente do Power Platform.
      • Método de autenticação: usar a autenticação somente do Microsoft Entra
      • Defina o administrador do Microsoft Entra: selecione Definir administrador e selecione seu próprio usuário.
    • Selecione OK
  4. Computação + armazenamento: Uso Geral – Sem servidor
  5. Selecione Avançar: Rede
  6. Preencher:
    • Método de conectividade: ponto de extremidade público
    • Permitir que os serviços e recursos do Azure acessem este servidor: Sim
    • Adicionar o endereço IP do cliente atual: Sim
  7. Selecionar Revisão + criar ->Criar
  8. Aguarde até que a Implantação seja concluída e selecione Ir para o recurso

Implantar dados de exemplo

  1. Dentro do Visual Studio Code, selecione Extensões (Ctrl + Shift + X)

  2. Localize a extensão do SQL Server (mssql) na Barra de Atividades e abra-a ou use Ctrl + Alt + D

  3. Em Conexões, selecione + Adicionar Conexão

    Adicionar conexão na extensão do SQL Server do VS Code

  4. Na caixa de diálogo Conectar ao Banco de Dados , selecione Procurar no Azure, selecione sua assinatura, grupo de recursos (por exemplo: rg-codeapps-dev), Servidor (por exemplo: sql-codeapps-dev) e banco de dados (por exemplo sqldb-codeapps-dev )

  5. Em Tipo de Autenticação, selecione a ID do Microsoft Entra – Universal com suporte para MFA

  6. Verifique se o portal do Azure está aberto no navegador e selecione Entrar. Será solicitado a entrar, e, em seguida, verá:

    Prompt de login do Microsoft Entra para conexão SQL

  7. Selecione Connect

    Conectado ao Banco de Dados SQL do Azure no VS Code

  8. No painel do SQL SERVER, clique com o botão direito do mouse no banco de dados e selecione Nova Consulta

    Novo comando Consulta para banco de dados na extensão SQL do VS Code

  9. Na nova janela de consulta, cole o seguinte SQL:

    -- Drop existing objects if they exist
    IF OBJECT_ID('dbo.Projects', 'U') IS NOT NULL DROP TABLE dbo.Projects;
    
    -- =============================================
    -- CREATE TABLES
    -- =============================================
    
    -- Projects Table
    CREATE TABLE [dbo].[Projects](
        [ProjectId] [int] IDENTITY(1,1) NOT NULL,
        [Name] [nvarchar](255) NOT NULL,
        [Description] [nvarchar](max) NULL,
        [StartDate] [date] NULL,
        [EndDate] [date] NULL,
        [Status] [nvarchar](50) NOT NULL DEFAULT ('Planning'),
        [Priority] [nvarchar](20) NOT NULL DEFAULT ('Medium'),
        [Budget] [decimal](18, 2) NULL,
        [ProjectManagerEmail] [nvarchar](255) NOT NULL,
        [CreatedBy] [nvarchar](255) NOT NULL,
        [CreatedDate] [datetime2](7) NOT NULL DEFAULT (getutcdate()),
        [IsActive] [bit] NOT NULL DEFAULT (1),
        CONSTRAINT [PK_Projects] PRIMARY KEY ([ProjectId])
    );
    GO
    
    -- =============================================
    -- ADD CONSTRAINTS
    -- =============================================
    
    -- Project Status Check
    ALTER TABLE [dbo].[Projects] ADD CONSTRAINT [CK_Projects_Status] 
    CHECK ([Status] IN ('Planning', 'Active', 'On Hold', 'Completed', 'Cancelled'));
    
    -- Project Priority Check
    ALTER TABLE [dbo].[Projects] ADD CONSTRAINT [CK_Projects_Priority] 
    CHECK ([Priority] IN ('Low', 'Medium', 'High', 'Critical'));
    GO
    
    -- =============================================
    -- STORED PROCEDURES
    -- =============================================
    
    -- Get All Projects
    IF OBJECT_ID('dbo.GetAllProjects', 'P') IS NOT NULL DROP PROCEDURE dbo.GetAllProjects;
    GO
    CREATE PROCEDURE [dbo].[GetAllProjects]
    AS
    BEGIN
        SET NOCOUNT ON;
    
        SELECT 
            [ProjectId], [Name], [Description], [StartDate], [EndDate],
            [Status], [Priority], [Budget], [ProjectManagerEmail],
            [CreatedBy], [CreatedDate], [IsActive]
        FROM [dbo].[Projects]
        WHERE [IsActive] = 1
        ORDER BY [CreatedDate] DESC;
    END
    GO
    
    -- Create Project
    IF OBJECT_ID('dbo.CreateProject', 'P') IS NOT NULL DROP PROCEDURE dbo.CreateProject;
    GO
    CREATE PROCEDURE [dbo].[CreateProject]
        @Name NVARCHAR(255),
        @Description NVARCHAR(MAX) = NULL,
        @StartDate DATE = NULL,
        @EndDate DATE = NULL,
        @Status NVARCHAR(50) = 'Planning',
        @Priority NVARCHAR(20) = 'Medium',
        @Budget DECIMAL(18,2) = NULL,
        @ProjectManagerEmail NVARCHAR(255),
        @CreatedBy NVARCHAR(255)
    AS
    BEGIN
        SET NOCOUNT ON;
    
        INSERT INTO [dbo].[Projects] (
            [Name], [Description], [StartDate], [EndDate], 
            [Status], [Priority], [Budget], [ProjectManagerEmail], [CreatedBy]
        )
        VALUES (
            @Name, @Description, @StartDate, @EndDate,
            @Status, @Priority, @Budget, @ProjectManagerEmail, @CreatedBy
        );
    
        SELECT SCOPE_IDENTITY() as ProjectId;
    END
    GO
    
    -- Update Project
    IF OBJECT_ID('dbo.UpdateProject', 'P') IS NOT NULL DROP PROCEDURE dbo.UpdateProject;
    GO
    CREATE PROCEDURE [dbo].[UpdateProject]
        @ProjectId INT,
        @Name NVARCHAR(255) = NULL,
        @Description NVARCHAR(MAX) = NULL,
        @StartDate DATE = NULL,
        @EndDate DATE = NULL,
        @Status NVARCHAR(50) = NULL,
        @Priority NVARCHAR(20) = NULL,
        @Budget DECIMAL(18,2) = NULL,
        @ProjectManagerEmail NVARCHAR(255) = NULL
    AS
    BEGIN
        SET NOCOUNT ON;
    
        UPDATE [dbo].[Projects]
        SET 
            [Name] = ISNULL(@Name, [Name]),
            [Description] = ISNULL(@Description, [Description]),
            [StartDate] = ISNULL(@StartDate, [StartDate]),
            [EndDate] = ISNULL(@EndDate, [EndDate]),
            [Status] = ISNULL(@Status, [Status]),
            [Priority] = ISNULL(@Priority, [Priority]),
            [Budget] = ISNULL(@Budget, [Budget]),
            [ProjectManagerEmail] = ISNULL(@ProjectManagerEmail, [ProjectManagerEmail])
        WHERE [ProjectId] = @ProjectId AND [IsActive] = 1;
    
        SELECT @@ROWCOUNT as RowsAffected;
    END
    GO
    
    -- Delete Project (Soft Delete)
    IF OBJECT_ID('dbo.DeleteProject', 'P') IS NOT NULL DROP PROCEDURE dbo.DeleteProject;
    GO
    CREATE PROCEDURE [dbo].[DeleteProject]
        @ProjectId INT
    AS
    BEGIN
        SET NOCOUNT ON;
    
        UPDATE [dbo].[Projects]
        SET [IsActive] = 0
        WHERE [ProjectId] = @ProjectId AND [IsActive] = 1;
    
        SELECT @@ROWCOUNT as RowsAffected;
    END
    GO
    
    -- =============================================
    -- SAMPLE DATA
    -- =============================================
    
    -- Insert Sample Projects
    INSERT INTO [dbo].[Projects] ([Name], [Description], [StartDate], [EndDate], [Status], [Priority], [Budget], [ProjectManagerEmail], [CreatedBy]) VALUES
    ('Website Redesign', 'Complete redesign of company website with modern UI/UX', '2025-06-01', '2025-08-31', 'Active', 'High', 75000.00, 'sarah.johnson@company.com', 'admin@company.com'),
    ('Mobile App Development', 'Develop iOS and Android mobile application for customer portal', '2025-07-01', '2025-12-31', 'Planning', 'Critical', 150000.00, 'mike.chen@company.com', 'admin@company.com'),
    ('Database Migration', 'Migrate legacy database to cloud infrastructure', '2025-05-15', '2025-09-30', 'Active', 'Medium', 50000.00, 'lisa.williams@company.com', 'admin@company.com');
    GO
    
    PRINT 'Projects-only database schema created successfully with sample data!';
    
  10. Selecione o botão de execução verde (Ctrl-Shift-E) para executar a consulta.

  11. Você não deve ver erros na saída RESULTADOS DA CONSULTA .

Inicializar seu aplicativo de código

Se você ainda não tiver, crie e/ou inicialize seu aplicativo de código usando as instruções aqui: Crie um aplicativo do zero.

Criar uma conexão do SQL Server no Power Platform

  1. Abrir Power Apps

  2. Selecione seu ambiente

  3. Navegue até Conexões. Pode estar no ... Mais menu.

  4. Selecionar + Nova Conexão

    + Nova conexão no Power Apps

  5. Selecionar SQL Server

  6. Selecionar tipo de autenticação: ID Integrada do Microsoft Entra

  7. Selecione Criar e faça login no prompt de autenticação exibido

Adicionar conexões de tabela SQL ao seu aplicativo

  1. Liste as conexões disponíveis em seu ambiente. Você deve ver a conexão que criou:

    pac connection list
    

    Você deve ver uma lista semelhante a:

    Lista de conexões do Power Platform mostrando a conexão SQL

  2. Para adicionar a tabela de projetos ao projeto, copie a ID da conexão (a primeira coluna) e use o seguinte comando:

    pac code add-data-source -a "shared_sql" -c "[CONNECTION ID]"  -d "[SQL SERVER NAME].database.windows.net,[DATA BASE NAME]" -sp "dbo.GetAllProjects"
    

    Por exemplo:

    pac code add-data-source -a "shared_sql" -c "aaaa0000bb11222233cc444444dddddd"  -d "sql-codeapps-dev.database.windows.net,sqldb-codeapps-dev" -sp "dbo.GetAllProjects"
    
  3. Abra as pastas Services e Models e observe o código recém-gerado.

Adicionar tabela de projetos

  1. Usamos a interface do usuário fluente para mostrar uma tabela de projetos, portanto, faça downgrade para o React 18 e instale usando:

    npm install react@^18.0.0 react-dom@^18.0.0 @types/react@^18.0.0 @types/react-dom@^18.0.0
    npm install @fluentui/react-components
    
  2. Adicione um novo arquivo em src nome ProjectsTable.tsx com o seguinte código:

    /**
     * ProjectsTable Component - Displays project data from Power Platform in a sortable DataGrid
     */
    import React, { useEffect, useState, useCallback, useMemo } from 'react';
    import {
      DataGrid,
      DataGridHeader,
      DataGridRow,
      DataGridHeaderCell,
      DataGridCell,
      DataGridBody,
      TableColumnDefinition,
      TableRowId,
      Spinner,
      MessageBar,
      Badge,
      makeStyles,
      tokens,
    } from '@fluentui/react-components';
    import { GetAllProjectsService } from './Services/GetAllProjectsService';
    
    // String formatting utility for localizable messages
    const formatMessage = (template: string, params: Record<string, string | number> = {}): string => {
      return template.replace(/\{(\w+)\}/g, (match, key) => {
        const value = params[key];
        return value !== undefined ? String(value) : match;
      });
    };
    
    // Common UI messages
    const MESSAGE_STRINGS = {
      LOADING: 'Loading data...',
      NO_DATA: 'No data found.',
      GENERIC_ERROR: 'An unexpected error occurred',
      LOAD_ERROR: 'Failed to load data. Please try again.',
      PROJECT_COUNTER_SINGLE: 'Showing {count} project',
      PROJECT_COUNTER_PLURAL: 'Showing {count} projects',
      COLUMN_PROJECT_NAME: 'Project Name',
      COLUMN_DESCRIPTION: 'Description',
      COLUMN_START_DATE: 'Start Date',
      COLUMN_END_DATE: 'End Date',
      COLUMN_STATUS: 'Status',
      COLUMN_PRIORITY: 'Priority',
      ARIA_LABEL_DATA_GRID: 'Projects data grid',
    } as const;
    
    // Project data type
    type ProjectItem = {
      ProjectId?: number;
      Name?: string;
      Description?: string;
      StartDate?: string;
      EndDate?: string;
      Status?: string;
      Priority?: string;
      Budget?: number;
      ProjectManagerEmail?: string;
      CreatedBy?: string;
      CreatedDate?: string;
      IsActive?: boolean;
    };
    
    // DataGrid columns
    const COLUMNS: TableColumnDefinition<ProjectItem>[] = [
      {
        columnId: 'name',
        compare: (a, b) => (a.Name || '').localeCompare(b.Name || ''),
        renderHeaderCell: () => MESSAGE_STRINGS.COLUMN_PROJECT_NAME,
        renderCell: (item) => item.Name || '',
      },
      {
        columnId: 'description',
        compare: (a, b) => (a.Description || '').localeCompare(b.Description || ''),
        renderHeaderCell: () => MESSAGE_STRINGS.COLUMN_DESCRIPTION,
        renderCell: (item) => item.Description || '',
      },
      {
        columnId: 'startDate',
        compare: (a, b) => new Date(a.StartDate || '').getTime() - new Date(b.StartDate || '').getTime(),
        renderHeaderCell: () => MESSAGE_STRINGS.COLUMN_START_DATE,
        renderCell: (item) => item.StartDate ? new Date(item.StartDate).toLocaleDateString() : '',
      },
      {
        columnId: 'endDate',
        compare: (a, b) => new Date(a.EndDate || '').getTime() - new Date(b.EndDate || '').getTime(),
        renderHeaderCell: () => MESSAGE_STRINGS.COLUMN_END_DATE,
        renderCell: (item) => item.EndDate ? new Date(item.EndDate).toLocaleDateString() : '',
      }, {
        columnId: 'status',
        compare: (a, b) => (a.Status || '').localeCompare(b.Status || ''),
        renderHeaderCell: () => MESSAGE_STRINGS.COLUMN_STATUS,
        renderCell: (item) => <StatusBadge status={item.Status || ''} />,
      },
      {
        columnId: 'priority',
        compare: (a, b) => (a.Priority || '').localeCompare(b.Priority || ''),
        renderHeaderCell: () => MESSAGE_STRINGS.COLUMN_PRIORITY,
        renderCell: (item) => <PriorityBadge priority={item.Priority || ''} />,
      },
    ];
    
    // Row ID generator
    const getRowId = (item: ProjectItem): TableRowId =>
      item.ProjectId?.toString() || `temp-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
    
    // Extracts a user-friendly error message from various error types
    const extractErrorMessage = (
      error: unknown,
      fallbackMessage = MESSAGE_STRINGS.GENERIC_ERROR
    ): string => {
      if (error instanceof Error) {
        return error.message;
      }
      if (typeof error === 'string') {
        return error;
      } return fallbackMessage;
    };
    
    // Badge component for Priority
    const PriorityBadge: React.FC<{ priority: string }> = React.memo(({ priority }) => {
      const styles = useStyles();
      const badgeProps = useMemo(() => {
        const getPriorityAppearance = (priority: string) => {
          switch (priority?.toLowerCase()) {
            case 'critical':
              return { appearance: 'filled' as const, color: 'danger' as const };
            case 'high':
              return { appearance: 'filled' as const, color: 'important' as const };
            case 'medium':
              return { appearance: 'filled' as const, color: 'warning' as const };
            case 'low':
              return { appearance: 'filled' as const, color: 'success' as const };
            default:
              return { appearance: 'outline' as const, color: 'subtle' as const };
          }
        };
        return getPriorityAppearance(priority);
      }, [priority]);
    
      return (
        <Badge {...badgeProps} className={styles.badge}>
          {priority || 'Unknown'}
        </Badge>
      );
    });
    
    PriorityBadge.displayName = 'PriorityBadge';
    
    // Badge component for Status
    const StatusBadge: React.FC<{ status: string }> = React.memo(({ status }) => {
      const styles = useStyles();
      const badgeProps = useMemo(() => {
        const getStatusAppearance = (status: string) => {
          switch (status?.toLowerCase()) {
            case 'completed':
              return { appearance: 'filled' as const, color: 'success' as const };
            case 'active':
              return { appearance: 'filled' as const, color: 'brand' as const };
            case 'planning':
              return { appearance: 'filled' as const, color: 'informative' as const };
            case 'on hold':
              return { appearance: 'filled' as const, color: 'warning' as const };
            case 'cancelled':
              return { appearance: 'filled' as const, color: 'danger' as const };
            default:
              return { appearance: 'outline' as const, color: 'subtle' as const };
          }
        };
        return getStatusAppearance(status);
      }, [status]);
    
      return (
        <Badge {...badgeProps} className={styles.badge}>
          {status || 'Unknown'}
        </Badge>
      );
    });
    
    StatusBadge.displayName = 'StatusBadge';
    
    // Styles
    const useStyles = makeStyles({
      container: {
        padding: tokens.spacingVerticalXXL,
      },
      loadingContainer: {
        display: 'flex',
        alignItems: 'center',
        gap: tokens.spacingHorizontalS,
        padding: tokens.spacingVerticalXXL,
      },
      messageBar: {
        marginBottom: tokens.spacingVerticalXL,
      },
      projectCounter: {
        marginBottom: tokens.spacingVerticalM,
        fontSize: tokens.fontSizeBase200,
        color: tokens.colorNeutralForeground2,
      }, dataGrid: {
        width: '100%',
      },
      badge: {
        fontSize: tokens.fontSizeBase200,
        fontWeight: tokens.fontWeightMedium,
        textTransform: 'capitalize',
      },
    });
    
    // Custom hook to fetch and manage project data
    const useProjectsData = (): {
      projects: ProjectItem[];
      loading: boolean;
      error: string | null;
      refetch: () => Promise<void>;
    } => {
      const [projects, setProjects] = useState<ProjectItem[]>([]);
      const [loading, setLoading] = useState(true);
      const [error, setError] = useState<string | null>(null);
    
      const fetchProjects = useCallback(async () => {
        try {
          setLoading(true);
          setError(null); const result = await GetAllProjectsService.GetAllProjects();
          if (result.success && result.data?.ResultSets?.Table1) {
            const projectsData = Array.isArray(result.data.ResultSets.Table1)
              ? result.data.ResultSets.Table1 as ProjectItem[]
              : [result.data.ResultSets.Table1] as ProjectItem[];
            setProjects(projectsData);
          } else {
            const errorMsg = result.error instanceof Error
              ? result.error.message
              : result.error || MESSAGE_STRINGS.LOAD_ERROR;
            setError(errorMsg);
            console.error('Failed to fetch projects:', result.error);
          }
        } catch (error) {
          const errorMessage = extractErrorMessage(error, MESSAGE_STRINGS.GENERIC_ERROR);
          setError(errorMessage);
          console.error('Error fetching projects:', error);
        } finally {
          setLoading(false);
        }
      }, []);
    
      useEffect(() => {
        fetchProjects();
      }, [fetchProjects]);
    
      return { projects, loading, error, refetch: fetchProjects };
    };
    
    // UI Components
    const LoadingSpinner: React.FC = () => {
      const styles = useStyles();
      return (
        <div className={styles.loadingContainer}>
          <Spinner size="small" />
          <span>{MESSAGE_STRINGS.LOADING}</span>
        </div>
      );
    };
    
    const ErrorMessage: React.FC<{ error: string }> = ({ error }) => {
      const styles = useStyles();
      return (
        <MessageBar intent="error" className={styles.messageBar}>
          {error}
        </MessageBar>
      );
    };
    
    const EmptyState: React.FC = () => {
      const styles = useStyles();
      return (
        <MessageBar intent="info" className={styles.messageBar} style={{ textAlign: 'center' }}>
          {MESSAGE_STRINGS.NO_DATA}
        </MessageBar>
      );
    };
    
    const ProjectCounter: React.FC<{ count: number }> = ({ count }) => {
      const styles = useStyles();
    
      const counterMessage = useMemo(() => {
        return count === 1
          ? formatMessage(MESSAGE_STRINGS.PROJECT_COUNTER_SINGLE, { count })
          : formatMessage(MESSAGE_STRINGS.PROJECT_COUNTER_PLURAL, { count });
      }, [count]);
    
      return (
        <div className={styles.projectCounter}>
          {counterMessage}
        </div>
      );
    };
    
    // Main component
    const ProjectsTable: React.FC = () => {
      const styles = useStyles();
      const { projects, loading, error } = useProjectsData();
      const projectCount = useMemo(() => projects.length, [projects.length]);
      const memoizedProjects = useMemo(() => projects, [projects]);
      const dataGridProps = useMemo(() => ({
        items: memoizedProjects,
        columns: COLUMNS,
        sortable: true,
        getRowId,
        focusMode: "cell" as const,
        className: styles.dataGrid,
        "aria-label": MESSAGE_STRINGS.ARIA_LABEL_DATA_GRID,
      }), [memoizedProjects, styles.dataGrid]);
    
      if (loading) {
        return (
          <div className={styles.container}>
            <LoadingSpinner />
          </div>
        );
      }
    
      if (error) {
        return (
          <div className={styles.container}>
            <ErrorMessage error={error} />
          </div>
        );
      }
    
      if (projectCount === 0) {
        return (
          <div className={styles.container}>
            <EmptyState />
          </div>
        );
      }
      return (
        <div className={styles.container}>
          <ProjectCounter count={projectCount} />      <DataGrid {...dataGridProps}>
            <DataGridHeader>
              <DataGridRow>
                {({ renderHeaderCell }) => (
                  <DataGridHeaderCell>{renderHeaderCell()}</DataGridHeaderCell>
                )}
              </DataGridRow>
            </DataGridHeader>
            <DataGridBody<ProjectItem>>
              {({ item, rowId }) => (
                <DataGridRow<ProjectItem> key={rowId}>
                  {({ renderCell }) => (
                    <DataGridCell>{renderCell(item)}</DataGridCell>
                  )}
                </DataGridRow>
              )}
            </DataGridBody>
          </DataGrid>
        </div>
      );
    };
    
    export default React.memo(ProjectsTable);
    
    
  3. Adicione o FluentProvider e ProjectsTable para maint.tsx:

     import { StrictMode } from 'react'
     import { createRoot } from 'react-dom/client'
     import './index.css'
     import PowerProvider from './PowerProvider.tsx'
     import { FluentProvider, webLightTheme } from '@fluentui/react-components'
     import ProjectsTable from './ProjectsTable.tsx'
    
     createRoot(document.getElementById('root')!).render(
       <StrictMode>
         <PowerProvider>
           <FluentProvider theme={webLightTheme}>
             <ProjectsTable />
           </FluentProvider>
         </PowerProvider>
       </StrictMode>,
     )
    
    
  4. Execute seu aplicativo usando:

    npm run dev
    

    Na janela de comando que é aberta, abra o link do aplicativo fornecido:

    Console do servidor do Power SDK com a URL e o status do aplicativo

  5. Quando o aplicativo for aberto, você deverá ver uma caixa de diálogo de consentimento, selecione Permitir.

    Caixa de diálogo de consentimento solicitando permissões para o aplicativo

  6. Você deve ver a tabela de dados dos projetos:

    Projeta a grade de dados com colunas e selos classificáveis

Publicando o aplicativo no Power Apps

  1. Depois que o aplicativo estiver pronto para publicação e compartilhamento, verifique se o servidor do Vite foi interrompido usando Ctrl + C e use o seguinte PowerShell:

    npm run build
    pac code push
    
  2. Abra o aplicativo usando o link fornecido para testá-lo!

    Aplicativo publicado no Power Apps com link abrir aplicativo

Resolução de problemas

Esta seção aborda problemas comuns que você pode encontrar ao configurar aplicativos de código do Power Apps com o Banco de Dados SQL do Azure.

Problemas do Banco de Dados SQL do Azure

Você pode enfrentar esses problemas ao usar bancos de dados SQL do Azure.

Não é possível se conectar ao Banco de Dados SQL do Azure

Sintomas:

  • Erros no tempo limite de conexão
  • Falhas de autenticação ao se conectar com a extensão SQL do VS Code

Soluções:

  1. Verifique as configurações de firewall:

    • No portal do Azure, navegue até o SQL Server
    • Vá para SegurançaRede
    • Verifique se "Permitir que os serviços e recursos do Azure acessem este servidor" está definido como Sim
    • Adicionar o endereço IP do cliente atual às regras de firewall
  2. Verificar método de autenticação:

    • Verifique se você está usando a ID do Microsoft Entra – Universal com suporte de MFA no VS Code
    • Verifique se você está conectado à mesma conta do Azure no portal do Azure e no VS Code
    • Tente sair e voltar para atualizar os tokens de autenticação
  3. Verifique a conectividade de rede:

    # Test connectivity to SQL Server
    Test-NetConnection -ComputerName "your-sql-server.database.windows.net" -Port 1433
    

Erros de execução de consulta SQL

Sintomas:

  • Erros por permissão negada ao executar scripts SQL
  • Erros Objeto já existente

Soluções:

  1. Problemas de permissão:

    • Verifique se sua conta de usuário está definida como o administrador do Microsoft Entra para o SQL Server
    • Verifique se você tem db_owner ou as permissões apropriadas no banco de dados
  2. Erros de Existência do Objeto:

    • O script SQL inclui DROP instruções – elas são seguras para serem executadas várias vezes
    • Se você receber erros de restrição, execute as instruções de exclusão individualmente primeiro

problemas de Node.js e npm

Você pode enfrentar esses problemas ao usar Node.js e npm.

Porta 3000 já em uso

Sintomas:

  • "EADDRINUSE: endereço já em uso :::3000"
  • O servidor do Vite não inicia

Soluções:

  1. Encerrar o processo existente:

    # Find process using port 3000
    netstat -ano | findstr :3000
    # Kill the process (replace PID with actual process ID)
    taskkill /PID [PID] /F
    
  2. Use a porta alternativa:

    • Para usar uma porta diferente, atualize vite.config.ts
    • Atualizar a configuração do Power SDK adequadamente

Falhas na instalação do pacote

Sintomas:

  • Erros de instalação do npm
  • Erros não encontrados no módulo

Soluções:

  1. Limpar cache npm:

    npm cache clean --force
    npm install
    
  2. Excluir node_modules e Reinstalar:

    Remove-Item -Recurse -Force node_modules
    Remove-Item package-lock.json
    npm install
    
  3. Problemas de versão do Node.js:

    # Check Node version
    node --version
    # Should be LTS version (18.x or 20.x)
    

Erros de conexão em tempo de execução

Sintomas:

  • "Falha ao carregar dados" no aplicativo React
  • Erros Conexão recusada

Soluções:

  1. Verifique a conexão do Power Platform:

    • Verifique se a conexão do SQL Server está funcionando no Power Platform
    • Testar a conexão no Power Apps
  2. Problemas de consentimento:

    • Verifique se você dá consentimento quando o aplicativo é carregado pela primeira vez
    • Limpar o cache do navegador e tentar novamente
  3. Incompatibilidade de ambiente:

    • Verifique se você está executando o aplicativo no mesmo ambiente em que a conexão foi criada
    • Verifique se o perfil do navegador corresponde à sua conta do Power Platform