TripPin bagian 10 - Pelipatan kueri dasar
Catatan
Konten ini saat ini mereferensikan konten dari implementasi warisan untuk log di Visual Studio. Konten akan diperbarui dalam waktu dekat untuk mencakup Power Query SDK baru di Visual Studio Code.
Tutorial multi-bagian ini mencakup pembuatan ekstensi sumber data baru untuk Power Query. Tutorial ini dimaksudkan untuk dilakukan secara berurutan—setiap pelajaran dibangun pada konektor yang dibuat dalam pelajaran sebelumnya, secara bertahap menambahkan kemampuan baru ke konektor Anda.
Dalam pelajaran ini, Anda akan:
- Pelajari dasar-dasar pelipatan kueri
- Pelajari tentang fungsi Table.View
- Replikasi penanganan pelipatan kueri OData untuk:
$top
$skip
$count
$select
$orderby
Salah satu fitur canggih dari bahasa M adalah kemampuannya untuk mendorong pekerjaan transformasi ke satu atau beberapa sumber data yang mendasar. Kemampuan ini disebut sebagai Pelipatan Kueri (alat/teknologi lain juga merujuk ke fungsi serupa sebagai Predikat Pushdown, atau Delegasi Kueri).
Saat membuat konektor kustom yang menggunakan fungsi M dengan kemampuan pelipatan kueri bawaan, seperti OData.Feed atau Odbc.DataSource, konektor Anda secara otomatis mewarisi kemampuan ini secara gratis.
Tutorial ini mereplikasi perilaku pelipatan kueri bawaan untuk OData dengan menerapkan penangan fungsi untuk fungsi Table.View . Bagian tutorial ini mengimplementasikan beberapa handler yang lebih mudah diimplementasikan (yaitu, yang tidak memerlukan penguraian ekspresi dan pelacakan status).
Untuk memahami selengkapnya tentang kemampuan kueri yang mungkin ditawarkan layanan OData, buka Konvensi URL OData v4.
Catatan
Seperti yang dinyatakan sebelumnya, fungsi OData.Feed secara otomatis menyediakan kemampuan lipatan kueri. Karena seri TripPin memperlakukan layanan OData sebagai REST API biasa, menggunakan Web.Contents daripada OData.Feed, Anda harus mengimplementasikan penangan lipat kueri sendiri. Untuk penggunaan dunia nyata, kami sarankan Anda menggunakan OData.Feed jika memungkinkan.
Buka Gambaran Umum evaluasi kueri dan pelipatan kueri di Power Query untuk informasi selengkapnya tentang pelipatan kueri.
Menggunakan Table.View
Fungsi Table.View memungkinkan konektor kustom untuk mengambil alih penangan transformasi default untuk sumber data Anda. Implementasi Table.View akan menyediakan fungsi untuk satu atau beberapa handler yang didukung. Jika handler tidak terbendung, atau mengembalikan error
selama evaluasi, mesin M kembali ke handler defaultnya.
Saat konektor kustom menggunakan fungsi yang tidak mendukung pelipatan kueri implisit, seperti Web.Contents, penanganan transformasi default selalu dilakukan secara lokal. Jika REST API yang Anda sambungkan mendukung parameter kueri sebagai bagian dari kueri, Table.View memungkinkan Anda menambahkan pengoptimalan yang memungkinkan pekerjaan transformasi didorong ke layanan.
Fungsi Table.View memiliki tanda tangan berikut:
Table.View(table as nullable table, handlers as record) as table
Implementasi Anda membungkus fungsi sumber data utama Anda. Ada dua handler yang diperlukan untuk Table.View:
GetType
—mengembalikan hasil kueri yang diharapkantable type
GetRows
—mengembalikan hasil aktualtable
fungsi sumber data Anda
Implementasi paling sederhana akan mirip dengan contoh berikut:
TripPin.SuperSimpleView = (url as text, entity as text) as table =>
Table.View(null, [
GetType = () => Value.Type(GetRows()),
GetRows = () => GetEntity(url, entity)
]);
TripPinNavTable
Perbarui fungsi untuk memanggil TripPin.SuperSimpleView
daripada GetEntity
:
withData = Table.AddColumn(rename, "Data", each TripPin.SuperSimpleView(url, [Name]), type table),
Jika Anda menjalankan ulang pengujian unit, Anda akan melihat bahwa perilaku fungsi Anda tidak diubah. Dalam hal ini, implementasi Table.View Anda hanya melewati panggilan ke GetEntity
. Karena Anda belum menerapkan handler transformasi apa pun (belum), parameter asli url
tetap tidak tersentuh.
Implementasi awal Table.View
Implementasi Table.View di atas sederhana, tetapi tidak terlalu berguna. Implementasi berikut digunakan sebagai garis besar Anda—tidak mengimplementasikan fungsionalitas lipatan apa pun, tetapi memiliki perancah yang Anda butuhkan untuk melakukannya.
TripPin.View = (baseUrl as text, entity as text) as table =>
let
// Implementation of Table.View handlers.
//
// We wrap the record with Diagnostics.WrapHandlers() to get some automatic
// tracing if a handler returns an error.
//
View = (state as record) => Table.View(null, Diagnostics.WrapHandlers([
// Returns the table type returned by GetRows()
GetType = () => CalculateSchema(state),
// Called last - retrieves the data from the calculated URL
GetRows = () =>
let
finalSchema = CalculateSchema(state),
finalUrl = CalculateUrl(state),
result = TripPin.Feed(finalUrl, finalSchema),
appliedType = Table.ChangeType(result, finalSchema)
in
appliedType,
//
// Helper functions
//
// Retrieves the cached schema. If this is the first call
// to CalculateSchema, the table type is calculated based on
// the entity name that was passed into the function.
CalculateSchema = (state) as type =>
if (state[Schema]? = null) then
GetSchemaForEntity(entity)
else
state[Schema],
// Calculates the final URL based on the current state.
CalculateUrl = (state) as text =>
let
urlWithEntity = Uri.Combine(state[Url], state[Entity])
in
urlWithEntity
]))
in
View([Url = baseUrl, Entity = entity]);
Jika Anda melihat panggilan ke Table.View, Anda akan melihat fungsi pembungkus ekstra di handlers
sekitar rekaman—Diagnostics.WrapHandlers
. Fungsi pembantu ini ditemukan dalam modul Diagnostik (yang diperkenalkan dalam menambahkan pelajaran diagnostik ), dan memberi Anda cara yang berguna untuk secara otomatis melacak kesalahan apa pun yang dimunculkan oleh penangan individual.
Fungsi GetType
dan GetRows
diperbarui untuk menggunakan dua fungsi pembantu baru —CalculateSchema
dan CalculateUrl
. Saat ini, implementasi fungsi-fungsi tersebut cukup mudah —perhatikan bahwa fungsi tersebut berisi bagian dari apa yang sebelumnya dilakukan oleh GetEntity
fungsi.
Terakhir, perhatikan bahwa Anda menentukan fungsi internal (View
) yang menerima state
parameter.
Saat Anda mengimplementasikan lebih banyak handler, mereka akan secara rekursif memanggil fungsi internal View
, memperbarui, dan meneruskannya state
saat dijalankan.
TripPinNavTable
Perbarui fungsi sekali lagi, ganti panggilan ke TripPin.SuperSimpleView
dengan panggilan ke fungsi baruTripPin.View
, dan jalankan ulang pengujian unit. Anda belum akan melihat fungsionalitas baru, tetapi Sekarang Anda memiliki garis besar yang solid untuk pengujian.
Menerapkan pelipatan kueri
Karena mesin M secara otomatis kembali ke pemrosesan lokal saat kueri tidak dapat dilipat, Anda harus mengambil beberapa langkah tambahan untuk memvalidasi bahwa handler Table.View Anda berfungsi dengan benar.
Cara manual untuk memvalidasi perilaku lipatan adalah dengan menonton permintaan URL yang dibuat pengujian unit Anda menggunakan alat seperti Fiddler. Atau, pembuatan log diagnostik yang Anda tambahkan untuk TripPin.Feed
memancarkan URL lengkap yang dijalankan, yang harus menyertakan parameter string kueri OData yang ditambahkan handler Anda.
Cara otomatis untuk memvalidasi pelipatan kueri adalah dengan memaksa eksekusi pengujian unit Anda gagal jika kueri tidak sepenuhnya terlipat. Anda dapat melakukan ini dengan membuka properti proyek, dan mengatur Kesalahan pada Kegagalan Lipatan ke True. Dengan pengaturan ini diaktifkan, kueri apa pun yang memerlukan pemrosesan lokal menghasilkan kesalahan berikut:
Kami tidak dapat melipat ekspresi ke sumbernya. Silakan coba ekspresi yang lebih sederhana.
Anda dapat menguji ini dengan menambahkan yang baru Fact
ke file pengujian unit Anda yang berisi satu atau beberapa transformasi tabel.
// Query folding tests
Fact("Fold $top 1 on Airlines",
#table( type table [AirlineCode = text, Name = text] , {{"AA", "American Airlines"}} ),
Table.FirstN(Airlines, 1)
)
Catatan
Pengaturan Kesalahan pada Kegagalan Lipatan adalah pendekatan "semua atau tidak sama sekali". Jika Anda ingin menguji kueri yang tidak dirancang untuk dilipat sebagai bagian dari pengujian unit, Anda harus menambahkan beberapa logika kondisional untuk mengaktifkan/menonaktifkan pengujian yang sesuai.
Bagian yang tersisa dari tutorial ini masing-masing menambahkan handler Table.View baru. Anda mengambil pendekatan Test Driven Development (TDD), tempat Anda pertama kali menambahkan pengujian unit yang gagal, lalu menerapkan kode M untuk mengatasinya.
Bagian handler berikut menjelaskan fungsionalitas yang disediakan oleh handler, sintaks kueri setara OData, pengujian unit, dan implementasinya. Menggunakan kode perancah yang dijelaskan sebelumnya, setiap implementasi handler memerlukan dua perubahan:
- Menambahkan handler ke Table.View yang memperbarui
state
rekaman. - Memodifikasi
CalculateUrl
untuk mengambil nilai daristate
dan menambahkan ke parameter string url dan/atau kueri.
Menangani Table.FirstN dengan OnTake
Handler OnTake
menerima count
parameter, yang merupakan jumlah maksimum baris yang akan diambil dari GetRows
.
Dalam istilah OData, Anda dapat menerjemahkan ini ke parameter kueri $top .
Anda menggunakan pengujian unit berikut:
// Query folding tests
Fact("Fold $top 1 on Airlines",
#table( type table [AirlineCode = text, Name = text] , {{"AA", "American Airlines"}} ),
Table.FirstN(Airlines, 1)
),
Fact("Fold $top 0 on Airports",
#table( type table [Name = text, IataCode = text, Location = record] , {} ),
Table.FirstN(Airports, 0)
),
Pengujian ini keduanya menggunakan Table.FirstN untuk memfilter ke hasil yang diatur ke jumlah baris X pertama. Jika Anda menjalankan pengujian ini dengan Kesalahan pada Kegagalan Lipatan diatur ke False
(default), pengujian harus berhasil, tetapi jika Anda menjalankan Fiddler (atau memeriksa log jejak), perhatikan bahwa permintaan yang Anda kirim tidak berisi parameter kueri OData apa pun.
Jika Anda mengatur Kesalahan pada Kegagalan Pelipatan ke True
, pengujian gagal dengan Please try a simpler expression.
kesalahan. Untuk memperbaiki kesalahan ini, Anda perlu menentukan handler Table.View pertama Anda untuk OnTake
.
Handler OnTake
terlihat seperti kode berikut:
OnTake = (count as number) =>
let
// Add a record with Top defined to our state
newState = state & [ Top = count ]
in
@View(newState),
Fungsi ini CalculateUrl
diperbarui untuk mengekstrak Top
nilai dari state
rekaman, dan mengatur parameter yang tepat dalam string kueri.
// Calculates the final URL based on the current state.
CalculateUrl = (state) as text =>
let
urlWithEntity = Uri.Combine(state[Url], state[Entity]),
// Uri.BuildQueryString requires that all field values
// are text literals.
defaultQueryString = [],
// Check for Top defined in our state
qsWithTop =
if (state[Top]? <> null) then
// add a $top field to the query string record
defaultQueryString & [ #"$top" = Number.ToText(state[Top]) ]
else
defaultQueryString,
encodedQueryString = Uri.BuildQueryString(qsWithTop),
finalUrl = urlWithEntity & "?" & encodedQueryString
in
finalUrl
Menjalankan ulang pengujian unit, perhatikan bahwa URL yang Anda akses sekarang berisi $top
parameter . Karena pengodean URL, $top
muncul sebagai %24top
, tetapi layanan OData cukup pintar untuk mengonversinya secara otomatis.
Menangani Table.Skip dengan OnSkip
Handler OnSkip
sangat mirip OnTake
. Ini menerima count
parameter, yang merupakan jumlah baris yang akan dilewati dari kumpulan hasil. Handler ini diterjemahkan dengan baik ke parameter kueri $skip OData.
Pengujian unit:
// OnSkip
Fact("Fold $skip 14 on Airlines",
#table( type table [AirlineCode = text, Name = text] , {{"EK", "Emirates"}} ),
Table.Skip(Airlines, 14)
),
Fact("Fold $skip 0 and $top 1",
#table( type table [AirlineCode = text, Name = text] , {{"AA", "American Airlines"}} ),
Table.FirstN(Table.Skip(Airlines, 0), 1)
),
Implementasi:
// OnSkip - handles the Table.Skip transform.
// The count value should be >= 0.
OnSkip = (count as number) =>
let
newState = state & [ Skip = count ]
in
@View(newState),
Mencocokkan pembaruan ke CalculateUrl
:
qsWithSkip =
if (state[Skip]? <> null) then
qsWithTop & [ #"$skip" = Number.ToText(state[Skip]) ]
else
qsWithTop,
Informasi selengkapnya: Table.Skip
Menangani Table.SelectColumns dengan OnSelectColumns
Handler OnSelectColumns
dipanggil saat pengguna memilih atau menghapus kolom dari kumpulan hasil. Handler menerima list
nilai text
, mewakili satu atau beberapa kolom yang akan dipilih.
Dalam istilah OData, operasi ini memetakan ke opsi kueri $select .
Keuntungan pemilihan kolom lipat menjadi jelas saat Anda berhadapan dengan tabel dengan banyak kolom. Operator $select
menghapus kolom yang tidak dipilih dari kumpulan hasil, menghasilkan kueri yang lebih efisien.
Pengujian unit:
// OnSelectColumns
Fact("Fold $select single column",
#table( type table [AirlineCode = text] , {{"AA"}} ),
Table.FirstN(Table.SelectColumns(Airlines, {"AirlineCode"}), 1)
),
Fact("Fold $select multiple column",
#table( type table [UserName = text, FirstName = text, LastName = text],{{"russellwhyte", "Russell", "Whyte"}}),
Table.FirstN(Table.SelectColumns(People, {"UserName", "FirstName", "LastName"}), 1)
),
Fact("Fold $select with ignore column",
#table( type table [AirlineCode = text] , {{"AA"}} ),
Table.FirstN(Table.SelectColumns(Airlines, {"AirlineCode", "DoesNotExist"}, MissingField.Ignore), 1)
),
Dua pengujian pertama memilih jumlah kolom yang berbeda dengan Table.SelectColumns, dan menyertakan panggilan Table.FirstN untuk menyederhanakan kasus pengujian.
Catatan
Jika pengujian hanya mengembalikan nama kolom (menggunakan Table.ColumnNames dan bukan data apa pun, permintaan ke layanan OData tidak akan pernah benar-benar dikirim. Ini karena panggilan ke GetType
akan mengembalikan skema, yang berisi semua informasi yang dibutuhkan mesin M untuk menghitung hasilnya.
Pengujian ketiga menggunakan opsi MissingField.Ignore , yang memberi tahu mesin M untuk mengabaikan kolom yang dipilih yang tidak ada dalam tataan hasil. Handler OnSelectColumns
tidak perlu khawatir tentang opsi ini—mesin M menanganinya secara otomatis (artinya, kolom yang hilang tidak disertakan dalam columns
daftar).
Catatan
Opsi lain untuk Table.SelectColumns, MissingField.UseNull, memerlukan konektor untuk mengimplementasikan OnAddColumn
handler. Ini akan dilakukan dalam pelajaran berikutnya.
Implementasi untuk OnSelectColumns
melakukan dua hal:
- Menambahkan daftar kolom yang dipilih ke
state
. - Menghitung
Schema
ulang nilai sehingga Anda dapat mengatur jenis tabel yang tepat.
OnSelectColumns = (columns as list) =>
let
// get the current schema
currentSchema = CalculateSchema(state),
// get the columns from the current schema (which is an M Type value)
rowRecordType = Type.RecordFields(Type.TableRow(currentSchema)),
existingColumns = Record.FieldNames(rowRecordType),
// calculate the new schema
columnsToRemove = List.Difference(existingColumns, columns),
updatedColumns = Record.RemoveFields(rowRecordType, columnsToRemove),
newSchema = type table (Type.ForRecord(updatedColumns, false))
in
@View(state &
[
SelectColumns = columns,
Schema = newSchema
]
),
CalculateUrl
diperbarui untuk mengambil daftar kolom dari status, dan menggabungkannya (dengan pemisah) untuk $select
parameter .
// Check for explicitly selected columns
qsWithSelect =
if (state[SelectColumns]? <> null) then
qsWithSkip & [ #"$select" = Text.Combine(state[SelectColumns], ",") ]
else
qsWithSkip,
Menangani Table.Sort dengan OnSort
Handler OnSort
menerima daftar rekaman jenis:
type [ Name = text, Order = Int16.Type ]
Setiap rekaman berisi Name
bidang, menunjukkan nama kolom, dan Order
bidang yang sama dengan Order.Ascending atau Order.Descending.
Dalam istilah OData, operasi ini memetakan ke opsi kueri $orderby .
$orderby
Sintaks memiliki nama kolom diikuti oleh asc
atau desc
untuk menunjukkan urutan naik atau turun. Saat Anda mengurutkan pada beberapa kolom, nilai dipisahkan dengan koma. columns
Jika parameter berisi lebih dari satu item, penting untuk mempertahankan urutan tampilannya.
Pengujian unit:
// OnSort
Fact("Fold $orderby single column",
#table( type table [AirlineCode = text, Name = text], {{"TK", "Turkish Airlines"}}),
Table.FirstN(Table.Sort(Airlines, {{"AirlineCode", Order.Descending}}), 1)
),
Fact("Fold $orderby multiple column",
#table( type table [UserName = text], {{"javieralfred"}}),
Table.SelectColumns(Table.FirstN(Table.Sort(People, {{"LastName", Order.Ascending}, {"UserName", Order.Descending}}), 1), {"UserName"})
)
Implementasi:
// OnSort - receives a list of records containing two fields:
// [Name] - the name of the column to sort on
// [Order] - equal to Order.Ascending or Order.Descending
// If there are multiple records, the sort order must be maintained.
//
// OData allows you to sort on columns that do not appear in the result
// set, so we do not have to validate that the sorted columns are in our
// existing schema.
OnSort = (order as list) =>
let
// This will convert the list of records to a list of text,
// where each entry is "<columnName> <asc|desc>"
sorting = List.Transform(order, (o) =>
let
column = o[Name],
order = o[Order],
orderText = if (order = Order.Ascending) then "asc" else "desc"
in
column & " " & orderText
),
orderBy = Text.Combine(sorting, ", ")
in
@View(state & [ OrderBy = orderBy ]),
Pembaruan untuk CalculateUrl
:
qsWithOrderBy =
if (state[OrderBy]? <> null) then
qsWithSelect & [ #"$orderby" = state[OrderBy] ]
else
qsWithSelect,
Menangani Table.RowCount dengan GetRowCount
Tidak seperti handler kueri lain yang Anda terapkan, GetRowCount
handler mengembalikan satu nilai—jumlah baris yang diharapkan dalam tataan hasil. Dalam kueri M, nilai ini biasanya akan menjadi hasil transformasi Table.RowCount .
Anda memiliki beberapa opsi berbeda tentang cara menangani nilai ini sebagai bagian dari kueri OData:
- Parameter kueri $count, yang mengembalikan hitungan sebagai bidang terpisah dalam tataan hasil.
- Segmen jalur /$count, yang hanya mengembalikan jumlah total, sebagai nilai skalar.
Kelemahan pendekatan parameter kueri adalah Anda masih perlu mengirim seluruh kueri ke layanan OData. Karena hitungan kembali sebaris sebagai bagian dari kumpulan hasil, Anda harus memproses halaman pertama data dari kumpulan hasil. Meskipun proses ini masih lebih efisien daripada membaca seluruh tataan hasil dan menghitung baris, proses ini mungkin masih lebih banyak pekerjaan daripada yang ingin Anda lakukan.
Keuntungan dari pendekatan segmen jalur adalah Anda hanya menerima satu nilai skalar dalam hasilnya. Pendekatan ini membuat seluruh operasi jauh lebih efisien. Namun, seperti yang dijelaskan dalam spesifikasi OData, segmen jalur /$count mengembalikan kesalahan jika Anda menyertakan parameter kueri lain, seperti $top
atau $skip
, yang membatasi kegunaannya.
Dalam tutorial ini, Anda menerapkan GetRowCount
handler menggunakan pendekatan segmen jalur. Untuk menghindari kesalahan yang akan Anda dapatkan jika parameter kueri lain disertakan, Anda memeriksa nilai status lainnya, dan mengembalikan "kesalahan yang tidak diimpikan" (...
) jika Anda menemukannya. Mengembalikan kesalahan apa pun dari handler Table.View memberi tahu mesin M bahwa operasi tidak dapat dilipat, dan harus kembali ke handler default sebagai gantinya (yang dalam hal ini akan menghitung jumlah total baris).
Pertama, tambahkan pengujian unit:
// GetRowCount
Fact("Fold $count", 15, Table.RowCount(Airlines)),
/$count
Karena segmen jalur mengembalikan nilai tunggal (dalam format biasa/teks) daripada tataan hasil JSON, Anda juga harus menambahkan fungsi internal baru (TripPin.Scalar
) untuk membuat permintaan dan menangani hasilnya.
// Similar to TripPin.Feed, but is expecting back a scalar value.
// This function returns the value from the service as plain text.
TripPin.Scalar = (url as text) as text =>
let
_url = Diagnostics.LogValue("TripPin.Scalar url", url),
headers = DefaultRequestHeaders & [
#"Accept" = "text/plain"
],
response = Web.Contents(_url, [ Headers = headers ]),
toText = Text.FromBinary(response)
in
toText;
Implementasi kemudian menggunakan fungsi ini (jika tidak ada parameter kueri lain yang ditemukan dalam state
):
GetRowCount = () as number =>
if (Record.FieldCount(Record.RemoveFields(state, {"Url", "Entity", "Schema"}, MissingField.Ignore)) > 0) then
...
else
let
newState = state & [ RowCountOnly = true ],
finalUrl = CalculateUrl(newState),
value = TripPin.Scalar(finalUrl),
converted = Number.FromText(value)
in
converted,
Fungsi CalculateUrl
diperbarui untuk menambahkan /$count
ke URL jika RowCountOnly
bidang diatur dalam state
.
// Check for $count. If all we want is a row count,
// then we add /$count to the path value (following the entity name).
urlWithRowCount =
if (state[RowCountOnly]? = true) then
urlWithEntity & "/$count"
else
urlWithEntity,
Pengujian unit baru Table.RowCount
sekarang harus lulus.
Untuk menguji kasus fallback, Anda menambahkan pengujian lain yang memaksa kesalahan.
Pertama, tambahkan metode pembantu try
yang memeriksa hasil operasi untuk kesalahan pelipatan.
// Returns true if there is a folding error, or the original record (for logging purposes) if not.
Test.IsFoldingError = (tryResult as record) =>
if ( tryResult[HasError]? = true and tryResult[Error][Message] = "We couldn't fold the expression to the data source. Please try a simpler expression.") then
true
else
tryResult;
Kemudian tambahkan pengujian yang menggunakan Table.RowCount dan Table.FirstN untuk memaksa kesalahan.
// test will fail if "Fail on Folding Error" is set to false
Fact("Fold $count + $top *error*", true, Test.IsFoldingError(try Table.RowCount(Table.FirstN(Airlines, 3)))),
Catatan penting di sini adalah bahwa pengujian ini sekarang mengembalikan kesalahan jika Kesalahan pada Kesalahan Lipatan diatur ke false
, karena Table.RowCount
operasi kembali ke handler lokal (default). Menjalankan pengujian dengan Kesalahan pada Kesalahan Lipatan diatur ke true
penyebab Table.RowCount
gagal, dan memungkinkan pengujian berhasil.
Kesimpulan
Menerapkan Table.View untuk konektor Anda menambahkan sejumlah besar kompleksitas ke kode Anda. Karena mesin M dapat memproses semua transformasi secara lokal, menambahkan handler Table.View tidak mengaktifkan skenario baru untuk pengguna Anda, tetapi menghasilkan pemrosesan yang lebih efisien (dan pengguna yang berpotensi lebih bahagia). Salah satu keuntungan utama handler Table.View bersifat opsional adalah memungkinkan Anda menambahkan fungsionalitas baru secara bertahap tanpa memengaruhi kompatibilitas mundur untuk konektor Anda.
Untuk sebagian besar konektor, handler penting (dan dasar) untuk diimplementasikan adalah OnTake
(yang diterjemahkan ke $top
dalam OData), karena membatasi jumlah baris yang dikembalikan. Pengalaman Power Query selalu melakukan baris OnTake
1000
saat menampilkan pratinjau di navigator dan editor kueri, sehingga pengguna Anda mungkin melihat peningkatan performa yang signifikan saat bekerja dengan himpunan data yang lebih besar.