Jaa


TripPin-osa 10 – Peruskyselyn delegointi lähteeseen

Muistiinpano

Tämä sisältö viittaa tällä hetkellä visual studion lokien vanhan toteutuksen sisältöön. Sisältö päivitetään lähitulevaisuudessa kattamaan uusi Power Query SDK Visual Studio Codessa.

Tässä moniosaisessa opetusohjelmassa käsitellään uuden tietolähdelaajennuksen luomista Power Querylle. Opetusohjelma on tarkoitus tehdä järjestyksessä – jokainen oppitunti perustuu aiemmilla oppitunneilla luotuun liittimeen ja lisää uusia ominaisuuksia liittimeen.

Tällä oppitunnilla:

  • Opi kyselyn delegoinnin lähteeseen delegoinnin perusteet
  • Lue lisätietoja Table.View-funktiosta
  • Replikoi OData-kyselyn delegointi lähteeseen -käsittelijät toimenpiteille:
  • $top
  • $skip
  • $count
  • $select
  • $orderby

Yksi M-kielen tehokkaista ominaisuuksista on sen kyky työntää muunnostyöntöjä yhteen tai useampaan pohjana olevaan tietolähteeseen. Tätä ominaisuutta kutsutaan nimellä Kyselyn delegointi (muut työkalut tai tekniikat viittaavat myös samaan funktioon kuin Predicate Pushdown tai Query Delegation).

Kun luot mukautetun liittimen, joka käyttää M-funktiota, jossa on sisäiset Kyselyn delegointi lähteeseen -ominaisuudet, kuten OData.Feed tai Odbc.DataSource, liittimesi perii automaattisesti tämän ominaisuuden maksutta.

Tämä opetusohjelma replikoi ODatan sisäiset kyselyn taitostoiminnot ottamalla käyttöön Table.View-funktion funktiokäsittelijöitä. Tässä opetusohjelman osassa toteutetaan joitakin helpompia käsittelijöitä (eli sellaisia, jotka eivät edellytä lausekkeen jäsentämistä ja tilan seurantaa).

Jos haluat lisätietoja OData-palvelun tarjoamista kyselytoiminnoista, siirry kohtaan OData v4 URL-käytännöt.

Muistiinpano

Kuten aiemmin mainittiin, OData.Feed-funktio tarjoaa automaattisesti kyselyn delegointi lähteeseen -ominaisuudet. Koska TripPin-sarja käsittelee OData-palvelua tavallisena REST-ohjelmointirajapintana käyttäen Web.Contentsia OData.Feedin sijaan, sinun on itse toteutettava Kyselyn delegointi lähteeseen -käsittelijät. Suosittelemme, että käytät OData.Feediä reaalimaailman käytössä aina, kun se on mahdollista.

Lisätietoja kyselyn delegoinnista lähteeseen on Power Queryn kyselyn arvioinnin ja kyselyn lähteeseen delegoinnin yleiskatsauksessa.

Table.View'n käyttäminen

Table.View-funktiolla mukautettu liitin voi ohittaa tietolähteen oletusmuunnoskäsittelijät. Table.View-toteutus tarjoaa funktion yhdelle tai useammalle tuetuista käsittelijöistä. Jos käsittelijää ei ole tarkoitus toteuttaa tai se palauttaa arvioinnin aikana virheilmoituksen error , M-moduuli palaa oletuskäsittelijäänsä.

Kun mukautettu liitin käyttää funktiota, joka ei tue implisiittistä kyselyn delegointia lähteeseen, kuten Web.Contents, oletusmuunnoskäsittelijät suoritetaan aina paikallisesti. Jos REST-ohjelmointirajapinta, johon olet muodostamassa yhteyttä, tukee kyselyparametreja osana kyselyä, Table.View'n avulla voit lisätä optimointeja, jotka mahdollistavat muunnostyön siirtämisen palveluun.

Table.View-funktiolla on seuraava allekirjoitus:

Table.View(table as nullable table, handlers as record) as table

Toteutus rivittää päätietolähdefunktion. Table.View'lle on kaksi pakollista käsittelijää:

  • GetType– palauttaa kyselytuloksen odotetun table type
  • GetRows— palauttaa tietolähdefunktion todellisen table tuloksen

Yksinkertaisin toteutus olisi seuraavan esimerkin kaltainen:

TripPin.SuperSimpleView = (url as text, entity as text) as table =>
    Table.View(null, [
        GetType = () => Value.Type(GetRows()),
        GetRows = () => GetEntity(url, entity)
    ]);

TripPinNavTable Päivitä funktio kutsumaan TripPin.SuperSimpleView kohteen sijaanGetEntity:

withData = Table.AddColumn(rename, "Data", each TripPin.SuperSimpleView(url, [Name]), type table),

Jos suoritat yksikkötestit uudelleen, näet, että funktion toiminta ei ole muuttunut. Tässä tapauksessa Table.View-toteutus on yksinkertaisesti välittämässä kutsua kohteeseen GetEntity. Koska et ole ottanut käyttöön muunnoskäsittelijöitä (vielä), alkuperäistä url parametria ei käsitellä.

Table.View:n alkuperäinen toteutus

Yllä oleva Table.View-toteutus on yksinkertainen, mutta ei kovin hyödyllinen. Seuraavaa toteutusta käytetään perustoimintona – siinä ei käytetä mitään lähteeseen delegointia, mutta siinä on sen tekemiseen tarvitsemasi rakenne.

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]);

Jos katsot Table.View-kutsua, näet tietueen ympärillä ylimääräisen rivitysfunktionhandlers.Diagnostics.WrapHandlers Tämä aputoiminto löytyy Diagnostiikka-moduulista (joka otettiin käyttöön diagnostiikan lisäyskurssilla ) ja tarjoaa hyödyllisen tavan jäljittää automaattisesti yksittäisten käsittelijöiden esiin tuomat virheet.

- ja GetRows -GetTypefunktiot päivitetään, jotta voit hyödyntää kahta uutta apufunktiota –CalculateSchema ja CalculateUrl. Tällä hetkellä näiden funktioiden toteutukset ovat melko yksinkertaisia – huomaa, että ne sisältävät osia siitä, mitä funktio oli aiemmin tehnyt GetEntity .

Huomaa, että määrität sisäisen funktion (View), joka hyväksyy parametrin state . Kun otat käyttöön enemmän käsittelijöitä, he kutsuvat rekursiivisesti sisäistä View funktiota päivittäen ja välittämällä niitä state samalla, kun ne etenevät.

TripPinNavTable Päivitä funktio uudelleen, korvaa kutsu TripPin.SuperSimpleView kutsulla uuteen TripPin.View funktioon ja suorita yksikkötestit uudelleen. Et näe vielä uusia toimintoja, mutta käytössäsi on nyt vakaa perustaso testausta varten.

Kyselyn lähteeseen delegoinnin toteuttaminen

Koska M-moduuli palaa automaattisesti paikalliseen käsittelyyn, kun kyselyä ei voida delegoida lähteeseen, sinun on suoritettava joitakin lisätoimia sen vahvistamiseksi, että Table.View-käsittelijät toimivat oikein.

Manuaalinen tapa vahvistaa taitostoiminta on seurata yksikkötestien URL-pyyntöjä Fiddler-työkalun avulla. Vaihtoehtoisesti lisäämäsi TripPin.Feed diagnostiikan kirjaus lähettää suoritettavan KOKO URL-osoitteen, johon sisältyvät käsittelijöiden lisäämät OData-kyselymerkkijonoparametrit.

Automaattinen tapa vahvistaa kyselyn delegointi lähteeseen on pakottaa yksikkötestin suorittaminen epäonnistumaan, jos kysely ei täysin taita. Voit tehdä tämän avaamalla projektin ominaisuudet ja määrittämällä Virhe-asetukseksi Taitettava virhe arvoon Tosi. Kun tämä asetus on käytössä, paikallinen käsittely edellyttää seuraavaa kyselyä. Tämä aiheuttaa seuraavan virheen:

Lauseketta ei voitu delegoida lähteeseen. Kokeile yksinkertaisempaa lauseketta.

Voit testata tätä lisäämällä yksikkötestitiedostoon uuden Fact , joka sisältää yhden tai useamman taulukon muunnoksen.

// Query folding tests
Fact("Fold $top 1 on Airlines", 
    #table( type table [AirlineCode = text, Name = text] , {{"AA", "American Airlines"}} ), 
    Table.FirstN(Airlines, 1)
)

Muistiinpano

Virhe Vian delegointi lähteeseen -asetus on kaikki tai ei mitään -lähestymistapa. Jos haluat testata kyselyitä, joita ei ole suunniteltu taitettavaksi osana yksikkötestejä, sinun on lisättävä ehdollista logiikkaa testien käyttöönottamiseksi tai ottamiseksi pois käytöstä vastaavasti.

Tämän opetusohjelman muissa osissa lisätään kukin uusi Table.View-käsittelijä . Olet omaksumassa TDD (Test Driven Development) -lähestymistavan, jossa lisäät ensin epäonnistuneet yksikkötestit ja otat sitten M-koodin käyttöön niiden ratkaisemiseksi.

Seuraavissa käsittelijän osissa kuvataan käsittelijän tarjoama toiminto, OData-vastaava kyselysyntaksi, yksikkötestit ja toteutus. Aiemmin kuvattua rakennekoodia käyttämällä kunkin käsittelijän toteutus edellyttää kahta muutosta:

  • Käsittelijän lisääminen Table.View-taulukkoon, joka päivittää tietueenstate.
  • Muokkaamalla CalculateUrl voit hakea arvot - state palvelusta ja lisätä ne URL-osoitteen ja/tai kyselymerkkijonon parametreihin.

Table.FirstN:n käsittely OnTaken kanssa

Käsittelijä OnTake vastaanottaa parametrin count , joka on :sta GetRowsvastaanotettavien rivien enimmäismäärä. OData-termeillä voit kääntää tämän $top kyselyparametriksi.

Käytät seuraavia yksikkötestejä:

// 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)
),

Nämä testit käyttävät table.FirstN-funktiota suodattamaan tulosjoukkoon, joka on rivien ensimmäinen X-määrä. Jos suoritat nämä testit niin, että Virhe on Taitettava virhe -asetuksena False (oletus), testien pitäisi onnistua, mutta jos suoritat Fiddler-komennon (tai tarkistat jäljityslokit), huomaa, että lähettämäsi pyyntö ei sisällä mitään OData-kyselyparametreja.

Diagnostiikan jäljitys.

Jos määrität Virhe- taittovirheen arvoksi True, testit epäonnistuvat ja Please try a simpler expression. virhe ilmenee. Voit korjata tämän virheen määrittämällä ensimmäisen Table.View-käsittelijän toiminnolle OnTake.

Käsittelijä OnTake näyttää seuraavalta koodilta:

OnTake = (count as number) =>
    let
        // Add a record with Top defined to our state
        newState = state & [ Top = count ]
    in
        @View(newState),

Funktio CalculateUrl päivitetään, jotta se poimii Top arvon tietueesta state , ja se määrittää oikean parametrin kyselymerkkijonossa.

// 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

Kun suoritat yksikkötestit uudelleen, huomaa, että URL-osoite, jota käytät, sisältää nyt parametrin $top . URL-koodauksen $top vuoksi näet muodossa %24top, mutta OData-palvelu on tarpeeksi älykäs muuntaakseen sen automaattisesti.

Diagnostiikan jäljitys ja yläreuna.

Table.Skipin käsittely OnSkipin kanssa

Käsittelijä OnSkip muistuttaa .OnTake Se saa parametrin count , joka on tulosjoukosta ohitettujen rivien määrä. Tämä käsittelijä muuntaa kätevästi OData $skip -kyselyparametrin.

Yksikkötestit:

// 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)
),

Täytäntöönpano:

// OnSkip - handles the Table.Skip transform.
// The count value should be >= 0.
OnSkip = (count as number) =>
    let
        newState = state & [ Skip = count ]
    in
        @View(newState),

Vastaavat päivitykset kohteeseen CalculateUrl:

qsWithSkip = 
    if (state[Skip]? <> null) then
        qsWithTop & [ #"$skip" = Number.ToText(state[Skip]) ]
    else
        qsWithTop,

Lisätietoja: Table.Skip

Table.SelectColumns-käsittely OnSelectColumns-sarakkeen avulla

Käsittelijää OnSelectColumns kutsutaan, kun käyttäjä valitsee tai poistaa sarakkeita tulosjoukosta. Käsittelijä vastaanottaa listtext arvoja, jotka edustavat yhtä tai useampaa valittavaa saraketta.

OData-termein tämä toiminto yhdistää $select -kyselyasetukseen.

Sarakkeen valinnan lähteeseen delegoinnin etu käy selväksi, kun käsittelet taulukoita, joissa on useita sarakkeita. Operaattori $select poistaa valitsemattomat sarakkeet tulosjoukosta, mikä tehostaa kyselyitä.

Yksikkötestit:

// 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)
),

Kahdessa ensimmäisessä testissä valitaan eri määrä sarakkeita Table.SelectColumns-funktion avulla ja sisällytetään Table.FirstN-kutsu, joka yksinkertaistaa testitapausta.

Muistiinpano

Jos testi vain palauttaa sarakkeiden nimet (käyttäen Table.ColumnNames-kohdetta eikä mitään tietoja, pyyntöä OData-palveluun ei koskaan lähetetä. Tämä johtuu siitä, että kutsu GetType palauttaa rakenteen, joka sisältää kaikki tiedot, joita M-moduuli tarvitsee tuloksen laskemiseen.

Kolmannessa testissä käytetään MissingField.Ignore-asetusta , joka kehottaa M-moduulia ohittamaan kaikki valitut sarakkeet, joita tulosjoukossa ei ole. Käsittelijän OnSelectColumns ei tarvitse huolehtia tästä vaihtoehdosta – M-moduuli käsittelee sen automaattisesti (eli puuttuvat sarakkeet eivät sisälly columns luetteloon).

Muistiinpano

Toinen Table.SelectColumns-asetus, MissingField.UseNull, edellyttää liitintä käsittelijän OnAddColumn käyttöönottoon. Tämä tehdään seuraavalla oppitunnilla.

OnSelectColumns Toteutus tekee kaksi asiaa:

  • Lisää valittujen sarakkeiden luettelon kohteeseen state.
  • Laskee arvon uudelleen, Schema jotta voit määrittää oikean taulukkotyypin.
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 päivitetään, jotta sarakkeiden luettelo noudetaan osavaltiosta, ja ne yhdistetään parametrille $select (erottimella).

// Check for explicitly selected columns
qsWithSelect =
    if (state[SelectColumns]? <> null) then
        qsWithSkip & [ #"$select" = Text.Combine(state[SelectColumns], ",") ]
    else
        qsWithSkip,

Handling Table.Sort with OnSort

Käsittelijä OnSort vastaanottaa luettelon tietueista, jotka ovat tyyppiä:

type [ Name = text, Order = Int16.Type ]

Kukin tietue sisältää kentän, joka Name ilmaisee sarakkeen nimen, ja Order kentän, jonka arvo on Order.Ascending tai Order.Descending.

OData-termeissä tämä toiminto yhdistää $orderby kyselyasetukseen. Syntaksissa $orderby on sarakkeen nimi, jota asc seuraa tai desc joka ilmaisee nousevaa tai laskevaa järjestystä. Kun lajittelet useita sarakkeita, arvot erotetaan toisistaan pilkulla. columns Jos parametri sisältää useamman kuin yhden kohteen, on tärkeää säilyttää niiden järjestys.

Yksikkötestit:

// 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"})
)

Täytäntöönpano:

// 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 ]),

Päivitykset kohteeseen CalculateUrl:

qsWithOrderBy = 
    if (state[OrderBy]? <> null) then
        qsWithSelect & [ #"$orderby" = state[OrderBy] ]
    else
        qsWithSelect,

Table.RowCount-käsittely GetRowCount-funktion avulla

Toisin kuin muut kyselykäsittelijät, jotka olet toteuttamassa, GetRowCount käsittelijä palauttaa yksittäisen arvon eli tulosjoukossa odotetun rivien määrän. M-kyselyssä tämä arvo on yleensä Table.RowCount-muunnoksen tulos.

Sinulla on muutamia eri vaihtoehtoja, miten voit käsitellä tätä arvoa osana OData-kyselyä:

Kyselyparametrin huono puoli on se, että sinun on edelleen lähetettävä koko kysely OData-palveluun. Koska määrä tulee takaisin tekstiin osana tulosjoukkoa, sinun on käsiteltävä tulosjoukon ensimmäinen tietosivu. Vaikka tämä prosessi on vielä tehokkaampi kuin koko tulosjoukon lukeminen ja rivien laskeminen, se on luultavasti vielä enemmän työtä kuin haluat.

Polkusegmenttimenetelmän etu on, että saat tuloksessa vain yhden skalaariarvon. Tämä lähestymistapa tekee koko toiminnosta paljon tehokkaamman. Kuitenkin OData-määrityksessä kuvatulla tavalla /$count-polkusegmentti palauttaa virheen, jos sisällytät mukaan muita kyselyparametreja, kuten $top tai $skip, jotka rajoittavat sen hyödyllisyyttä.

Tässä opetusohjelmassa toteutit käsittelijän GetRowCount polkusegmenttimenetelmän avulla. Jos muita kyselyparametreja ei sisällytetä virheisiin, valitsit muiden tilan arvojen varalta ja palauttit "keskeneräisen virheen" (...), jos sellaisia oli. Virhe palautetaan Table.View-käsittelijästä, joka ilmoittaa M-moduulille, että toimintoa ei voi delegoida lähteeseen, ja sen pitäisi palata sen sijaan oletuskäsittelijään (joka tässä tapauksessa laskisi rivien kokonaismäärän).

Lisää ensin yksikkötesti:

// GetRowCount
Fact("Fold $count", 15, Table.RowCount(Airlines)),

/$count Koska polkusegmentti palauttaa yksittäisen arvon (vain teksti -muodossa) JSON-tulosjoukon sijaan, sinun on myös lisättävä uusi sisäinen funktio (TripPin.Scalar), jotta voit tehdä pyynnön ja käsitellä tulosta.

// 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;

Toteutus käyttää sitten tätä funktiota (jos muita kyselyparametreja ei löydy kohdasta 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,

Funktio CalculateUrl päivitetään URL-osoitteen loppuun, /$count jos RowCountOnly kenttä on määritetty kohteessa 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,

Uuden Table.RowCount yksikkötestin pitäisi nyt läpäistä.

Jos haluat testata varatapausta, lisää toinen testi, joka pakottaa virheen.

Lisää ensin apumenetelmä, joka tarkistaa toiminnon tuloksen try delegointivirheen.

// 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;

Lisää sitten testi, joka pakottaa virheen sekä Table.RowCount- että Table.FirstN-arvon avulla.

// 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)))),

Tärkeä huomautus tässä on, että tämä testi palauttaa nyt virheen, jos Virhe taitettavassa virhe -arvossa falseon , koska Table.RowCount toiminto palaa paikalliseen (oletus) käsittelijään. Suorittamalla testit Virhe taitettaessa virhe -asetuksen arvoksi true vikasietoisuuden Table.RowCount aiheuttaja, ja antaa testille mahdollisuuden onnistua.

Yhteenveto

Table.View'n käyttöönotto liittimelle lisää koodiin merkittävästi monimutkaisuutta. Koska M-moduuli voi käsitellä kaikki muunnokset paikallisesti, Table.View-käsittelijöiden lisääminen ei mahdollista uusia skenaarioita käyttäjillesi, vaan se johtaa tehokkaampaan prosessointiin (ja mahdollisesti onnellisempiin käyttäjiin). Yksi Table.View -käsittelijöiden valinnaisen olemisen tärkeimmistä eduista on se, että sen avulla voit lisätä uusia toimintoja lisäävästi vaikuttamatta yhteensopivuuteen liittimesi kanssa taaksepäin.

Useimmilla liittimillä on tärkeä (ja perus)käsittelijä, joka on OnTake käytössä (joka tarkoittaa $top ODataa), koska se rajoittaa palautettavien rivien määrää. Power Query -käyttökokemus suorittaa aina rivin OnTake1000 , kun esikatseluja näytetään siirtymistoiminnossa ja kyselyeditorissa, joten käyttäjät saattavat nähdä merkittäviä suorituskyvyn parannuksia käsiteltäessä suurempia tietojoukkoja.