บทช่วยสอน: กําหนดตารางเวลาการคัดลอกสภาพแวดล้อมและการนําเข้าข้อมูลอัตโนมัติโดยใช้ Azure DevOps

การรักษาสภาพแวดล้อม Sandbox ให้เป็นปัจจุบันด้วยข้อมูลการผลิตเป็นความต้องการในการดําเนินงานทั่วไปสําหรับลูกค้าแอปการเงินและการดําเนินงาน ด้วยการดําเนินการกระบวนการนี้โดยอัตโนมัติโดยใช้ Azure DevOps ผู้ดูแลระบบสามารถกําหนดเวลาการทําสําเนาแบบใช้งานจริงไปยัง Sandbox และติดตามด้วยการนําเข้าแพคเกจข้อมูลเพื่อใช้การกําหนดค่าเฉพาะสภาพแวดล้อมโดยอัตโนมัติ

ในบทช่วยสอนนี้ เรียนรู้วิธีการ:

  • ตั้งค่าการเชื่อมต่อบริการ Azure DevOps โดยใช้สหพันธ์ข้อมูลประจําตัวของปริมาณงาน
  • สร้างไปป์ไลน์ตามกําหนดเวลาที่คัดลอกสภาพแวดล้อมการผลิตไปยัง Sandbox
  • นําเข้าแพคเกจข้อมูลการเงินและการดําเนินงานโดยอัตโนมัติหลังจากการคัดลอกเสร็จสมบูรณ์
  • ทําความเข้าใจบทบาทของผู้ใช้ DBMovementAPI สําหรับระบบหลังการคัดลอกอัตโนมัติ
  • (ไม่บังคับ) ทําสําเนาโดยไม่ทําธุรกรรมโดยใช้ Power Platform API เพื่อลดปริมาณการใช้พื้นที่จัดเก็บข้อมูล

ในฐานะตัวอย่างของสถานการณ์นี้ ลูกค้าต้องการรีเฟรชสภาพแวดล้อม Sandbox ของตนจากการผลิตทุกสุดสัปดาห์ หลังจากการคัดลอกเสร็จสิ้น แพคเกจข้อมูลที่ประกอบด้วยการตั้งค่าเฉพาะสภาพแวดล้อม (เช่น พารามิเตอร์อีเมล การกําหนดค่าชุดงาน หรือจุดสิ้นสุดการรวม) จะถูกนําเข้าโดยอัตโนมัติเพื่อให้ Sandbox พร้อมสําหรับการใช้งานในวันจันทร์

ก่อนที่คุณจะเริ่มต้น

  • สภาพแวดล้อมต้นทางคือสภาพแวดล้อมการผลิตของคุณ (ไม่ว่าจะเป็นสภาพแวดล้อม Lifecycle Services หรือสภาพแวดล้อมแบบรวมในศูนย์การจัดการ Power Platform)
  • สภาพแวดล้อมเป้าหมายคือสภาพแวดล้อม Sandbox แบบรวมที่โฮสต์โดย Microsoft Dataverse หากต้องการเรียนรู้วิธีการปรับใช้ โปรดดูบทช่วยสอน: เตรียมใช้งานสภาพแวดล้อมใหม่ด้วยเทมเพลตที่ใช้ ERP
  • คุณต้องเตรียมใช้งานสภาพแวดล้อมทั้งสองในภูมิภาคเดียวกัน สําหรับข้อมูลทั่วไปเกี่ยวกับการคัดลอกสภาพแวดล้อม ให้ดู คัดลอกสภาพแวดล้อม
  • คุณต้องมีองค์กร Azure DevOps และโครงการที่มีสิทธิ์ในการสร้างไปป์ไลน์และการเชื่อมต่อบริการ
  • ติดตั้งส่วนขยาย เครื่องมือสร้างแพลตฟอร์ม Power จาก Visual Studio Marketplace ในองค์กร Azure DevOps ของคุณ ตรวจสอบให้แน่ใจว่า คุณมีเวอร์ชัน 2.0.69 หรือใหม่กว่า ซึ่งสนับสนุนการติดต่อกับข้อมูลประจําตัวของปริมาณงาน
  • เตรียมแพคเกจข้อมูล (.zip) ในพื้นที่ทํางานการจัดการข้อมูลของแอปการเงินและการดําเนินงานของคุณ แพคเกจนี้ประกอบด้วยเอนทิตีข้อมูลและการกําหนดค่าที่คุณต้องการนําเข้าลงใน Sandbox หลังจากการคัดลอกแต่ละครั้ง

เกี่ยวกับผู้ใช้ DBMovementAPI

แอปการเงินและการดําเนินงานประกอบรวมด้วยบัญชีผู้ใช้ทางเลือกที่คุณสามารถสร้างที่เรียกว่า DBMovementAPI เมื่อคุณทําสําเนาสภาพแวดล้อม บัญชีนี้จะเปิดใช้งานโดยอัตโนมัติในสภาพแวดล้อมเป้าหมายหากมีอยู่ในสภาพแวดล้อมต้นทาง ซึ่งมีความสําคัญเนื่องจากผู้ใช้ DBMovementAPI สามารถรับสิทธิ์ที่จําเป็นในการเรียกใช้ API แพคเกจการจัดการข้อมูล ซึ่งหมายความว่าไปป์ไลน์อัตโนมัติของคุณสามารถรับรองความถูกต้องและทริกเกอร์การนําเข้าข้อมูลทันทีหลังจากการคัดลอกเสร็จสมบูรณ์โดยไม่ต้องดําเนินการด้วยตนเองและไม่มีผู้ใช้อื่นที่เปิดใช้งานเพื่อเข้าถึงระบบนอกเหนือจากบัญชีผู้ดูแลระบบ

สำคัญ

ตรวจสอบให้แน่ใจว่าผู้ใช้ DBMovementAPI ถูกสร้างขึ้นในสภาพแวดล้อมแหล่งข้อมูล (การผลิต) ของคุณก่อนดําเนินการคัดลอก คุณอาจปิดใช้งานในสภาพแวดล้อมต้นทาง แต่ให้บทบาทความปลอดภัยที่เหมาะสมและเชื่อมโยงผู้ใช้นี้กับแอปพลิเคชัน Microsoft Entra ID เพื่อให้สามารถเข้าถึงได้โดยทางโปรแกรม หลังจากการคัดลอกเสร็จสมบูรณ์ ผู้ใช้รายนี้จะเปิดใช้งานโดยอัตโนมัติใน Sandbox เป้าหมายและสามารถใช้เพื่อดําเนินการขั้นตอนการนําเข้าข้อมูล

ขั้นตอนที่ 1: ลงทะเบียนแอปพลิเคชันใน Microsoft Entra ID

เพื่ออนุญาตให้ Azure DevOps โต้ตอบกับ Power Platform API และ API การจัดการข้อมูลด้านการเงินและการดําเนินงาน คุณจําเป็นต้องลงทะเบียนแอป Microsoft Entra ID

  1. ลงชื่อเข้าใช้พอร์ทัล Azure และไปที่การลงทะเบียนแอป>
  2. เลือก การลงทะเบียนใหม่
  3. ป้อนชื่อ เช่น AzDevOps-PowerPlatform-Pipeline และเลือก ลงทะเบียน
  4. โปรดสังเกต ID แอปพลิเคชัน (ไคลเอนต์) และ ID ไดเรกทอรี (ผู้เช่า) สําหรับการใช้งานในภายหลัง

ให้สิทธิ์ API

  1. ในการลงทะเบียนแอปของคุณ ไปที่สิทธิ์> APIเพิ่มสิทธิ์
  2. เลือกแท็บ API ที่องค์กรของฉันใช้ ค้นหา Microsoft Dynamics ERP (00000015-0000-0000-c0000-00000000000) และมอบสิทธิ์ที่ได้รับมอบให้ทั้งหมด
  3. เพิ่มแอปเป็น ผู้ใช้แอปพลิเคชัน ใน Power Platform ด้วยบทบาทความปลอดภัยของ ผู้ดูแลระบบ ทั้งในสภาพแวดล้อมต้นทางและเป้าหมาย บทบาทผู้ดูแลระบบช่วยให้สามารถทําสําเนา สํารอง และคืนค่าสภาพแวดล้อมได้

หมายเหตุ

สําหรับคําแนะนําโดยละเอียดเกี่ยวกับการลงทะเบียนผู้ใช้แอปพลิเคชันใน Power Platform ดูที่ สร้างผู้ใช้แอปพลิเคชัน

ขั้นตอนที่ 2 กําหนดค่าการเชื่อมต่อบริการด้วยสหพันธ์ข้อมูลประจําตัวของปริมาณงาน

การติดต่อกับภายนอกของข้อมูลประจําตัวของปริมาณงานช่วยลดความจําเป็นในความลับของไคลเอ็นต์โดยใช้ OpenID Connect (OIDC) เพื่อสร้างความน่าเชื่อถือระหว่าง Azure DevOps และ Microsoft Entra ID

สร้างการเชื่อมต่อบริการ Power Platform ใน Azure DevOps

  1. ในโครงการ Azure DevOps ของคุณ ไปที่การตั้งค่า>โครงการการเชื่อมต่อบริการเชื่อมต่อ>บริการใหม่
  2. ค้นหา และเลือก Power Platform
  3. เลือก การติดต่อกับภายนอกของข้อมูลประจําตัวของปริมาณงาน (ตัวอย่าง) เป็นวิธีการรับรองความถูกต้อง
  4. กรอกข้อมูลในเขตข้อมูลต่อไปนี้:
    • URL เซิร์ฟเวอร์: ป้อน URL ของสภาพแวดล้อม Power Platform เป้าหมายของคุณ (ตัวอย่างเช่น https://yourorg.crm.dynamics.com)
    • ID ผู้เช่า: ป้อนรหัสผู้เช่า Microsoft Entra ของคุณ
    • ID แอปพลิเคชัน: ป้อน ID ไคลเอ็นต์ของการลงทะเบียนแอปจากขั้นตอนที่ 1
  5. ตั้งชื่อการเชื่อมต่อบริการ (ตัวอย่างเช่น PowerPlatform-Prod) และเลือก บันทึก

สำคัญ

หลังจากบันทึก จับค่า ตัวออก และ ตัวระบุหัวเรื่อง ที่แสดงบนหน้าการเชื่อมต่อบริการ

เพิ่มข้อมูลประจําตัวภายนอกลงในการลงทะเบียนแอปของคุณ

  1. ในพอร์ทัล Azure ไปที่การลงทะเบียนแอปของคุณที่สร้างขึ้นในขั้นตอนที่ 1

  2. เลือก ใบรับรองและข้อมูลลับ> ข้อมูลประจําตัวภายนอก>เพิ่มข้อมูลประจําตัว

  3. เลือกสถานการณ์ ผู้ออกอื่น ๆ

  4. ตั้งค่าดังต่อไปนี้:

    • ผู้ออก: ป้อนค่าจากขั้นตอนก่อนหน้า
    • ตัวระบุหัวเรื่อง: ป้อนค่าจากขั้นตอนก่อนหน้า
  5. ใส่ ชื่อ สําหรับข้อมูลประจําตัว (ตัวอย่างเช่น azdo-federation) และเลือก เพิ่ม

ขั้นตอนที่ 3: สร้างไปป์ไลน์ Azure DevOps ที่กําหนดเวลาไว้

สร้างไปป์ไลน์ YAML ใหม่ในโครงการ Azure DevOps ของคุณที่ทํางานตามกําหนดการ คัดลอกสภาพแวดล้อมการผลิตไปยัง Sandbox แล้วนําเข้าแพคเกจข้อมูล

ไปป์ไลน์ YAML

สร้างไฟล์ที่มีชื่อ ว่า scheduled-copy-and-import.yml ในที่เก็บของคุณ

trigger: none

schedules:
  - cron: '0 2 * * 6'  # Runs at 2:00 AM UTC every Saturday
    displayName: 'Weekly Prod to Sandbox Copy'
    branches:
      include:
        - master
    always: true

pool:
  vmImage: 'windows-latest'

variables:
  - name: ServiceConnection
    value: 'PowerPlatform-Prod'
  - name: SourceEnvironmentUrl
    value: 'https://yourprod.crm.dynamics.com'
  - name: TargetEnvironmentUrl
    value: 'https://yoursandbox.crm.dynamics.com'
  - name: TargetEnvironmentName
    value: 'My Sandbox'
  - name: FinOpsEnvironmentUrl
    value: 'https://yoursandbox.operations.dynamics.com'
  - name: DataPackagePath
    value: '$(Build.SourcesDirectory)/DeveloperData/SampleTransactions.zip'

stages:
  - stage: CopyEnvironment
    displayName: 'Copy Production to Sandbox'
    jobs:
      - job: CopyProdToSandbox
        displayName: 'Copy environment'
        timeoutInMinutes: 360
        steps:
          - task: PowerPlatformToolInstaller@2
            displayName: 'Install Power Platform Build Tools'

          - task: PowerPlatformCopyEnvironment@2
            displayName: 'Copy Production to Sandbox'
            inputs:
              authenticationType: 'PowerPlatformSPN'
              PowerPlatformSPN: '$(ServiceConnection)'
              SourceEnvironmentUrl: '$(SourceEnvironmentUrl)'
              TargetEnvironmentUrl: '$(TargetEnvironmentUrl)'
              CopyType: 'FullCopy'
              OverrideFriendlyName: true
              FriendlyName: '$(TargetEnvironmentName)'
              SkipAuditData: true
              MaxAsyncWaitTime: 360  # Wait up to 6 hours for the copy to complete

  - stage: ImportDataPackage
    displayName: 'Import Data Package to Sandbox'
    dependsOn: CopyEnvironment
    condition: succeeded()
    jobs:
      - job: ImportData
        displayName: 'Import data package via D365 F&O API'
        steps:
          - task: PowerShell@2
            displayName: 'Import data package into finance and operations'
            inputs:
              targetType: 'inline'
              script: |
                # Variables
                $finOpsUrl = "$(FinOpsEnvironmentUrl)"
                $tenantId = "$(TenantId)"
                $clientId = "$(ClientId)"
                $dataPackagePath = "$(DataPackagePath)"
                $entityName = "SampleTransactions"

                # Authenticate using federated token
                # The pipeline's service connection handles auth for Power Platform tasks,
                # but for direct F&O API calls we use MSAL with the app registration.
                # If using client credentials, obtain a token:
                $resource = "$finOpsUrl"
                $tokenUrl = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
                $scope = "$finOpsUrl/.default"

                $body = @{
                    client_id     = $clientId
                    scope         = $scope
                    grant_type    = "client_credentials"
                    client_secret = "$(ClientSecret)"
                }

                Write-Host "Acquiring access token for finance and operations environment..."
                $tokenResponse = Invoke-RestMethod -Method Post -Uri $tokenUrl -Body $body -ContentType "application/x-www-form-urlencoded"
                $accessToken = $tokenResponse.access_token

                $headers = @{
                    "Authorization" = "Bearer $accessToken"
                    "Content-Type"  = "application/octet-stream"
                }

                # Step 1: Get the blob URL to upload the package
                Write-Host "Requesting writable blob URL from the data management API..."
                $getBlobUrl = "$finOpsUrl/data/DataManagementDefinitionGroups/Microsoft.Dynamics.DataEntities.GetAzureWriteUrl"
                $getBlobBody = @{
                    "uniqueFileName" = "SampleTransactions.zip"
                } | ConvertTo-Json

                $blobResponse = Invoke-RestMethod -Method Post -Uri $getBlobUrl -Headers @{
                    "Authorization" = "Bearer $accessToken"
                    "Content-Type"  = "application/json"
                } -Body $getBlobBody

                $blobUrl = $blobResponse.value

                # Step 2: Upload the data package to the blob URL
                Write-Host "Uploading data package to blob storage..."
                $packageBytes = [System.IO.File]::ReadAllBytes($dataPackagePath)
                Invoke-RestMethod -Method Put -Uri $blobUrl -Headers @{
                    "x-ms-blob-type" = "BlockBlob"
                    "Content-Type"   = "application/octet-stream"
                } -Body $packageBytes

                # Step 3: Initiate the import
                Write-Host "Initiating data package import..."
                $importUrl = "$finOpsUrl/data/DataManagementDefinitionGroups/Microsoft.Dynamics.DataEntities.ImportFromPackage"
                $importBody = @{
                    "packageUrl"             = $blobUrl
                    "definitionGroupId"      = $entityName
                    "executionId"            = ""
                    "execute"                = $true
                    "overwrite"              = $true
                    "legalEntityId"          = "USMF"
                } | ConvertTo-Json

                $importResponse = Invoke-RestMethod -Method Post -Uri $importUrl -Headers @{
                    "Authorization" = "Bearer $accessToken"
                    "Content-Type"  = "application/json"
                } -Body $importBody

                $executionId = $importResponse.value
                Write-Host "Data import initiated. Execution ID: $executionId"

                # Step 4: Poll for completion
                Write-Host "Polling for import completion..."
                $statusUrl = "$finOpsUrl/data/DataManagementDefinitionGroups/Microsoft.Dynamics.DataEntities.GetExecutionSummaryStatus"
                $complete = $false
                $maxRetries = 60
                $retryCount = 0

                while (-not $complete -and $retryCount -lt $maxRetries) {
                    Start-Sleep -Seconds 30
                    $retryCount++

                    $statusBody = @{
                        "executionId" = $executionId
                    } | ConvertTo-Json

                    $statusResponse = Invoke-RestMethod -Method Post -Uri $statusUrl -Headers @{
                        "Authorization" = "Bearer $accessToken"
                        "Content-Type"  = "application/json"
                    } -Body $statusBody

                    $status = $statusResponse.value
                    Write-Host "Attempt $retryCount - Import status: $status"

                    if ($status -eq "Succeeded") {
                        Write-Host "Data package import completed successfully."
                        $complete = $true
                    }
                    elseif ($status -eq "Failed" -or $status -eq "Canceled") {
                        Write-Error "Data package import failed with status: $status"
                        exit 1
                    }
                }

                if (-not $complete) {
                    Write-Error "Data package import timed out after $maxRetries attempts."
                    exit 1
                }
            env:
              TenantId: $(TenantId)
              ClientId: $(ClientId)
              ClientSecret: $(ClientSecret)

กำหนดค่าตัวแปรไปป์ไลน์

ในไปป์ไลน์ Azure DevOps ของคุณ ให้เพิ่มตัวแปรต่อไปนี้ (ทําเครื่องหมายความลับเป็น ข้อมูลลับ)

ตัวแปร คำอธิบาย ข้อมูลลับ
TenantId ID ผู้เช่า Microsoft Entra ของคุณ ไม่
ClientId ID แอปพลิเคชัน (ไคลเอ็นต์) จากการลงทะเบียนแอปของคุณ ไม่
ClientSecret ข้อมูลลับไคลเอ็นต์สําหรับการลงทะเบียนแอป (ใช้สําหรับการเรียก API การเงินและการดําเนินงาน) ใช่

หมายเหตุ

งาน Power Platform Build Tools จะใช้การเชื่อมต่อบริการกับการติดต่อกับข้อมูลประจําตัวของปริมาณงาน (ไม่จําเป็นต้องมีความลับ) อย่างไรก็ตาม การเรียกใช้ API โดยตรงไปยังจุดสิ้นสุดการจัดการข้อมูลการเงินและการดําเนินงานในปัจจุบันต้องการโฟลว์ข้อมูลประจําตัวของไคลเอ็นต์ จัดเก็บความลับของไคลเอ็นต์อย่างปลอดภัยเป็นตัวแปรลับของไปป์ไลน์หรือใน Azure Key Vault

ตัวเลือก: สําเนาแบบไม่ใช้ธุรกรรมโดยใช้ Power Platform API

งาน PowerPlatformCopyEnvironment@2 ที่ใช้ในไปป์ไลน์ด้านบนทําสําเนาเต็มของทั้งข้อมูลการกําหนดค่าและข้อมูลทรานแซคชัน หากคุณต้องการทําสําเนาที่ไม่มีการทําธุรกรรม – ซึ่งจะคัดลอกรหัส การกําหนดค่า ข้อมูลหลัก และข้อมูลอ้างอิง แต่ตัดทอนตารางธุรกรรมทิ้ง คุณจําเป็นต้องเรียกใช้ Power Platform Environment Copy API โดยตรง API นี้แสดงตัวเลือก executeAdvancedCopyForFinanceAndOperations ซึ่งไม่พร้อมใช้งานในงานสร้างเครื่องมือในวันนี้

การคัดลอกที่ไม่มีธุรกรรมช่วยลดการใช้ที่เก็บข้อมูลบนสภาพแวดล้อม Sandbox ได้อย่างมาก หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับวิธีการทํางานและตารางที่จะถูกตัดทอน โปรดดูบทช่วยสอน: ดําเนินการคัดลอกที่ไม่เกี่ยวกับธุรกรรมระหว่างสภาพแวดล้อม หากต้องการทําสําเนาที่ไม่มีการทําธุรกรรมผ่าน UI ศูนย์การจัดการ Power Platform แทนไปป์ไลน์ ให้ทําตามบทช่วยสอนนั้น

ข้อกําหนดเบื้องต้นเพิ่มเติมสําหรับสําเนาแบบไม่มีการทําธุรกรรม

POWER Platform Environment Copy API ใช้จุดสิ้นสุด (https://api.powerplatform.com) ที่แตกต่างจาก API Dataverse ที่ใช้โดยงานสร้างเครื่องมือ ความแตกต่างนี้จําเป็นต้องมีสองขั้นตอนการอนุญาตพิเศษสําหรับการลงทะเบียนแอปของคุณ

  1. การกําหนดบทบาท Power Platform RBAC (ขอบเขตผู้เช่า): คุณต้องกําหนดบทบาท ผู้สนับสนุนแพลตฟอร์ม Power ในขอบเขตผู้เช่า บทบาทนี้ให้สิทธิ์ในการเรียกใช้ API การจัดการสภาพแวดล้อม สําหรับคําแนะนําทีละขั้นตอน ดูบทช่วยสอน: กําหนดบทบาทการควบคุมการเข้าถึงตามบทบาทไปยังบริการหลัก สําหรับเบื้องหลังเกี่ยวกับแบบจําลอง RBAC โปรดดูที่การควบคุมการเข้าถึงตามบทบาทสําหรับศูนย์การจัดการ Power Platform

  2. ผู้ใช้แอปพลิเคชัน Dataverse (ขอบเขตสภาพแวดล้อม): นอกจากนี้ คุณยังต้องลงทะเบียนบริการหลักของคุณเป็น ผู้ใช้แอปพลิเคชัน ด้วยบทบาทการรักษาความปลอดภัย ของผู้ดูแลระบบ ในทั้งสภาพแวดล้อม Dataverse ของแหล่งข้อมูลและเป้าหมาย การลงทะเบียนนี้จําเป็นเนื่องจากการดําเนินการคัดลอกจะเข้าถึงทรัพยากรระดับสภาพแวดล้อม สําหรับคําแนะนํา ดูสร้างผู้ใช้แอปพลิเคชัน

หมายเหตุ

จําเป็นต้องมีการกําหนดบทบาท RBAC ในขอบเขตผู้เช่าเฉพาะในกรณีที่คุณกําลังดําเนินการคัดลอกที่ไม่มีธุรกรรมผ่าน API เท่านั้น สําเนาแบบเต็มมาตรฐานโดยใช้งาน PowerPlatformCopyEnvironment@2 (แสดงในขั้นตอนที่ 3) ต้องการเฉพาะผู้ใช้แอปพลิเคชัน Dataverse และการเชื่อมต่อบริการสร้างเครื่องมือ

ตัวแปรไปป์ไลน์เพิ่มเติมสําหรับสําเนาแบบไม่มีทรานแซคชัน

เพิ่มตัวแปรเหล่านี้ไปยังไปป์ไลน์ของคุณควบคู่ไปกับตัวแปรที่มีอยู่ (ทําเครื่องหมายความลับเป็น ข้อมูลลับ)

ตัวแปร คำอธิบาย ข้อมูลลับ
SourceEnvironmentId ID สภาพแวดล้อม (GUID) ของสภาพแวดล้อมการผลิตต้นทางของคุณ ไม่
TargetEnvironmentId ID สภาพแวดล้อม (GUID) ของสภาพแวดล้อม Sandbox เป้าหมายของคุณ ไม่

คำแนะนำ

คุณสามารถค้นหารหัสสภาพแวดล้อมในศูนย์การจัดการ Power Platform ได้โดยนําทางไปยังสภาพแวดล้อม เลือกสภาพแวดล้อม และคัดลอก ID จาก URL หน้ารายละเอียดสภาพแวดล้อมหรือบานหน้าต่างรายละเอียด

แทนที่ขั้นตอนการคัดลอก

เมื่อต้องการใช้สําเนาที่ไม่มีการทําธุรกรรม ให้แทนที่ขั้นตอน CopyEnvironment ในไปป์ไลน์ YAML ด้วยโค้ดต่อไปนี้ ขั้นตอนนี้ได้รับโทเค็นสําหรับ Power Platform API เริ่มต้นสําเนาด้วยตัวเลือกแบบไม่มีการทําธุรกรรมและการสํารวจจนกว่าจะเสร็จสิ้น

  - stage: CopyEnvironment
    displayName: 'Transactionless Copy Production to Sandbox'
    jobs:
      - job: CopyProdToSandbox
        displayName: 'Transactionless copy via Power Platform API'
        timeoutInMinutes: 360
        steps:
          - task: PowerShell@2
            displayName: 'Copy environment (transactionless)'
            inputs:
              targetType: 'inline'
              script: |
                # --- Configuration ---
                $tenantId = "$(TenantId)"
                $clientId = "$(ClientId)"
                $clientSecret = "$(ClientSecret)"
                $sourceEnvId = "$(SourceEnvironmentId)"
                $targetEnvId = "$(TargetEnvironmentId)"
                $apiVersion = "2022-03-01-preview"

                # --- Step 1: Acquire access token for Power Platform API ---
                Write-Host "Acquiring access token for api.powerplatform.com..."
                $tokenUrl = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/token"
                $tokenBody = @{
                    client_id     = $clientId
                    scope         = "https://api.powerplatform.com/.default"
                    grant_type    = "client_credentials"
                    client_secret = $clientSecret
                }

                $tokenResponse = Invoke-RestMethod -Method Post -Uri $tokenUrl `
                    -Body $tokenBody -ContentType "application/x-www-form-urlencoded"
                $accessToken = $tokenResponse.access_token

                $headers = @{
                    "Authorization" = "Bearer $accessToken"
                    "Content-Type"  = "application/json"
                }

                # --- Step 2: Initiate transactionless copy ---
                Write-Host "Initiating transactionless copy..."
                Write-Host "  Source: $sourceEnvId"
                Write-Host "  Target: $targetEnvId"

                $copyUrl = "https://api.powerplatform.com/environmentmanagement/environments/$targetEnvId/copy?api-version=$apiVersion"
                $copyBody = @{
                    sourceEnvironmentId = $sourceEnvId
                    copyType = "Full"
                    copyOptions = @{
                        skipAuditData = $true
                        executeAdvancedCopyForFinanceAndOperations = $true
                    }
                } | ConvertTo-Json -Depth 3

                $copyResponse = Invoke-WebRequest -Method Post -Uri $copyUrl `
                    -Headers $headers -Body $copyBody -UseBasicParsing

                if ($copyResponse.StatusCode -ne 202) {
                    Write-Error "Copy request failed with status $($copyResponse.StatusCode): $($copyResponse.Content)"
                    exit 1
                }

                # The 202 response includes a Location header with the operation URL
                $operationUrl = $copyResponse.Headers["Location"]
                if (-not $operationUrl) {
                    # Some responses return the operation URL in the body
                    $responseBody = $copyResponse.Content | ConvertFrom-Json
                    $operationUrl = $responseBody.operationUrl
                }

                Write-Host "Copy initiated. Polling operation status..."
                Write-Host "  Operation URL: $operationUrl"

                # --- Step 3: Poll for completion ---
                $complete = $false
                $maxRetries = 720   # 6 hours at 30-second intervals
                $retryCount = 0

                while (-not $complete -and $retryCount -lt $maxRetries) {
                    Start-Sleep -Seconds 30
                    $retryCount++

                    try {
                        $statusResponse = Invoke-RestMethod -Method Get `
                            -Uri $operationUrl -Headers $headers
                    }
                    catch {
                        Write-Warning "Status check attempt $retryCount failed: $_"
                        continue
                    }

                    $state = $statusResponse.state
                    if ($retryCount % 10 -eq 0) {
                        Write-Host "Attempt $retryCount - Operation state: $state"
                    }

                    if ($state -eq "Succeeded") {
                        Write-Host "Transactionless copy completed successfully."
                        $complete = $true
                    }
                    elseif ($state -eq "Failed") {
                        Write-Error "Copy operation failed. Details: $($statusResponse | ConvertTo-Json -Depth 5)"
                        exit 1
                    }
                }

                if (-not $complete) {
                    Write-Error "Copy operation timed out after $retryCount attempts."
                    exit 1
                }
            env:
              TenantId: $(TenantId)
              ClientId: $(ClientId)
              ClientSecret: $(ClientSecret)

ส่วนที่เหลือของไปป์ไลน์ (ขั้นตอน ImportDataPackage ) ยังคงไม่เปลี่ยนแปลง ระบบจะทํางานหลังจากสําเนาแบบไม่มีการทําธุรกรรมเสร็จสมบูรณ์เช่นเดียวกับสําเนาแบบเต็มมาตรฐาน

การแก้ไขปัญหาสําเนาแบบไม่มีธุรกรรม

ปัญหา ความละเอียด
403 ถูกห้ามเมื่อเรียกใช้คัดลอก API บริการหลักไม่มีบทบาท Power Platform Contributor RBAC ในขอบเขตผู้เช่า ทําตาม บทช่วยสอนการกําหนดบทบาท RBAC เพื่อมอบหมาย
401 ไม่ได้รับอนุญาตเมื่อเรียกใช้คัดลอก API ได้รับโทเค็นมาสําหรับผู้ชมที่ไม่ถูกต้อง ตรวจสอบให้แน่ใจว่าขอบเขตเป็น **https://api.powerplatform.com/.default**ไม่ใช่ URL ผันผันข้อมูล
การคัดลอกสําเร็จ แต่ธุรกรรมยังคงปรากฏอยู่ ตรวจสอบว่า executeAdvancedCopyForFinanceAndOperations ถูกตั้งค่าเป็น $true ในเนื้อความของคําขอ นอกจากนี้ ยืนยันว่าสภาพแวดล้อมต้นทางมีการอัปเดตแพลตฟอร์มล่าสุด — สําเนาแบบไม่มีธุรกรรมต้องใช้เวอร์ชันแพลตฟอร์มขั้นต่ํา
ข้อผิดพลาดผู้ใช้แอพลิเคชันที่ไม่พบ ตรวจสอบให้แน่ใจว่ามีการลงทะเบียนแอปในฐานะผู้ใช้แอปพลิเคชันที่มีบทบาท เป็นผู้ดูแลระบบ ทั้งในสภาพแวดล้อมแหล่งข้อมูลและสภาพแวดล้อม Dataverse เป้าหมาย

ขั้นตอนที่ 4: เตรียมแพคเกจข้อมูล

  1. ในสภาพแวดล้อมการเงินและการดําเนินงานต้นทางของคุณ ให้ไปที่การจัดการข้อมูล>พื้นที่ทํางาน
  2. สร้างโครงการส่งออกใหม่ที่มีเอนทิตีข้อมูลที่คุณต้องการโหลดลงใน Sandbox หลังจากแต่ละสําเนา ตัวอย่างเช่น ธุรกรรมตัวอย่าง ข้อมูลทดสอบ หรือการกําหนดค่าเฉพาะสภาพแวดล้อม
  3. เรียกใช้การส่งออกและดาวน์โหลดไฟล์ .zip ผลลัพธ์
  4. บันทึกไฟล์ .zip นี้ไปยังสาขา หลักของ ที่เก็บ Azure DevOps ของคุณที่ DeveloperData/SampleTransactions.zipที่ตรงกับตัวแปร DataPackagePath ในไปป์ไลน์ YAML

คำแนะนำ

หากต้องการกําหนดสิ่งที่จะนําเข้าหลังจากสําเนา ให้สร้างโครงการข้อมูลในพื้นที่ทํางานการจัดการข้อมูลที่มีชื่อตรงกับ definitionGroupId ใน YAML ของไปป์ไลน์ (ตัวอย่างเช่น SampleTransactions) โครงการนี้ต้องมีอยู่ในสภาพแวดล้อมเป้าหมาย เนื่องจากจะถูกเขียนทับในระหว่างการคัดลอกแต่ละครั้ง คุณอาจต้องสร้างใหม่หรือรวมไว้เป็นส่วนหนึ่งของแพคเกจข้อมูลของคุณ

ขั้นตอนที่ 5: เรียกใช้และตรวจสอบไปป์ไลน์

  1. ใน Azure DevOps ไปที่ ไปป์ไลน์ และเลือกไปป์ไลน์ที่คุณสร้างขึ้น
  2. เลือก เรียกใช้ไปป์ไลน์ เพื่อทริกเกอร์การเรียกใช้ด้วยตนเอง หรือรอการเรียกใช้ตามกําหนดเวลา
  3. ตรวจสอบขั้นตอน CopyEnvironment เพื่อยืนยันว่าการคัดลอกจาก Sandbox การผลิตเสร็จสิ้นเรียบร้อยแล้ว
  4. หลังจากการคัดลอกเสร็จสิ้น ขั้นตอน ImportDataPackage จะทริกเกอร์โดยอัตโนมัติ ตรวจสอบเพื่อยืนยันการนําเข้าแพคเกจข้อมูลเรียบร้อยแล้ว
  5. ลงชื่อเข้าใช้สภาพแวดล้อมการเงินและการดําเนินงานของ Sandbox ของคุณ และตรวจสอบข้อมูลที่นําเข้า

การแก้ไขปัญหา

ปัญหา ความละเอียด
การรับรองความถูกต้องของการเชื่อมต่อบริการล้มเหลว ตรวจสอบตัวระบุผู้ออกและหัวเรื่องในข้อมูลประจําตัวภายนอกของคุณตรงกับค่าที่แสดงบนหน้าการเชื่อมต่อบริการ Azure DevOps ตรวจสอบบันทึกไปป์ไลน์สําหรับค่าที่คาดไว้
คัดลอกการดําเนินการหมดเวลา สําเนาสภาพแวดล้อมอาจใช้เวลาหลายชั่วโมงสําหรับฐานข้อมูลขนาดใหญ่ timeoutInMinutesเพิ่มค่าในงานคัดลอก
การนําเข้าข้อมูลส่งกลับ 401 ไม่ได้รับอนุญาต ตรวจสอบให้แน่ใจว่ามีการเปิดใช้งานผู้ใช้ DBMovementAPI ในสภาพแวดล้อมต้นทางและการลงทะเบียนแอปของคุณมีสิทธิ์ที่จําเป็นในสภาพแวดล้อมเป้าหมาย
สถานะการนําเข้าข้อมูล ล้มเหลว ตรวจทานรายละเอียดการดําเนินการในประวัติงาน>ข้อมูลในสภาพแวดล้อมการเงินและการดําเนินงานของคุณสําหรับข้อผิดพลาดของเอนทิตีเฉพาะ

ขั้นตอนถัดไป