แชร์ผ่าน


เบื้องหลังฉากของไฟร์วอลล์ความเป็นส่วนตัวของข้อมูล

หมายเหตุ

ขณะนี้ระดับความเป็นส่วนตัวไม่พร้อมใช้งานในกระแสข้อมูล Power Platform แต่ทีมผลิตภัณฑ์กําลังทํางานเพื่อเปิดใช้งานฟังก์ชันนี้

หากคุณใช้ Power Query เป็นระยะเวลานานแล้ว คุณอาจเคยประสบ คุณมีการคิวรี่ออกไปเมื่อคุณได้รับข้อผิดพลาดทันทีที่ไม่มีจํานวนการค้นหาออนไลน์การปรับแต่งคิวรี่หรือการตีด้วยแป้นพิมพ์สามารถแก้ไขได้ ข้อผิดพลาดเช่น:

Formula.Firewall: Query 'Query1' (step 'Source') references other queries or steps, so it may not directly access a data source. Please rebuild this data combination.

หรืออาจจะ:

Formula.Firewall: Query 'Query1' (step 'Source') is accessing data sources that have privacy levels which cannot be used together. Please rebuild this data combination.

ข้อผิดพลาดเหล่านี้ Formula.Firewall เป็นผลลัพธ์ของไฟร์วอลล์ความเป็นส่วนตัวของข้อมูลของ Power Query (หรือที่เรียกว่าไฟร์วอลล์) ซึ่งในบางครั้งอาจดูเหมือนว่ามีอยู่แล้วเพื่อทําลายข้อมูลของนักวิเคราะห์ข้อมูลทั่วโลก อย่างไรก็ตามเชื่อหรือไม่ไฟร์วอลล์ทําหน้าที่เพื่อวัตถุประสงค์ที่สําคัญ ในบทความนี้ เราจะเจาะลึกในประทุนเพื่อทําความเข้าใจวิธีการทํางานได้ดียิ่งขึ้น ด้วยความเข้าใจที่มากขึ้นคุณจะหวังว่าจะสามารถวินิจฉัยและแก้ไขข้อผิดพลาดของไฟร์วอลล์ได้ดีขึ้นในอนาคต

นี่อะไรน่ะ

วัตถุประสงค์ของไฟร์วอลล์ความเป็นส่วนตัวของข้อมูลนั้นง่าย: มีเพื่อป้องกันไม่ให้ Power Query จากการรั่วไหลของข้อมูลระหว่างแหล่งข้อมูลโดยไม่ได้ตั้งใจ

เหตุใดจึงจำเป็น ฉันหมายถึง คุณสามารถสร้าง M บางตัวที่จะส่งผ่านค่า SQL ไปยังตัวดึงข้อมูล OData ได้ แต่นี่อาจเป็นการรั่วไหลของข้อมูลอย่างตั้งใจ ผู้เขียน Mashup จะ (หรืออย่างน้อยก็ควร) รู้ว่าพวกเขากําลังทําเช่นนี้ เหตุใดความจําเป็นในการป้องกันการรั่วไหลของข้อมูลโดยไม่ได้ตั้งใจ

คําตอบ? พับ

พับ

การ พับเป็นคําที่อ้างถึงการแปลงนิพจน์ใน M (เช่น ตัวกรอง เปลี่ยนชื่อ การรวม และอื่นๆ) ให้เป็นการดําเนินการกับแหล่งข้อมูลดิบ (เช่น SQL, OData และอื่นๆ) ส่วนสําคัญของพลังของ Power Query มาจากข้อเท็จจริงที่ว่า PQ สามารถแปลงการดําเนินการที่ผู้ใช้ดําเนินการผ่านส่วนติดต่อผู้ใช้เป็น SQL ที่ซับซ้อนหรือภาษาแหล่งข้อมูล Backend อื่น ๆ โดยที่ผู้ใช้ไม่จําเป็นต้องรู้ภาษาดังกล่าว ผู้ใช้จะได้รับประโยชน์ด้านประสิทธิภาพการทํางานของการดําเนินการแหล่งข้อมูลแบบเนทีฟ ด้วย UI ที่ใช้งานง่ายซึ่งสามารถแปลงแหล่งข้อมูลทั้งหมดได้โดยใช้ชุดคําสั่งทั่วไป

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

นี่คือการรั่วไหลของข้อมูลที่ไม่ได้ตั้งใจเกิดขึ้น

ลองจินตนาการว่าคุณกําลังเข้าร่วมข้อมูล SQL ที่รวมหมายเลขประกันสังคมของพนักงานด้วยผลลัพธ์ของตัวดึงข้อมูล OData ภายนอก และคุณพบว่าหมายเลขประกันสังคมจาก SQL ถูกส่งไปยังบริการ OData อย่างฉับพลัน ข่าวร้ายใช่ไหม?

นี่คือประเภทของสถานการณ์ที่ไฟร์วอลล์มีวัตถุประสงค์เพื่อป้องกัน

ทํางานอย่างไร

ไฟร์วอลล์มีอยู่แล้วเพื่อป้องกันไม่ให้ข้อมูลจากแหล่งข้อมูลหนึ่งถูกส่งไปยังแหล่งอื่นโดยไม่ได้ตั้งใจ ง่ายพอ

แล้วมันทําภารกิจนี้ให้สําเร็จได้อย่างไร

ทําสิ่งนี้โดยการแบ่งคิวรี M ของคุณออกเป็นสิ่งที่เรียกว่าพาร์ติชันและบังคับใช้กฎต่อไปนี้:

  • พาร์ติชันอาจเข้าถึงแหล่งข้อมูลที่เข้ากันได้ หรืออ้างอิงพาร์ติชันอื่น ๆ แต่ไม่ใช่ทั้งสองอย่าง

ง่าย แต่สับสน พาร์ติชันคืออะไร อะไรทําให้แหล่งข้อมูลสองแหล่ง "เข้ากันได้"? และทําไมไฟร์วอลล์ควรดูแลหากพาร์ติชั่นต้องการเข้าถึงแหล่งข้อมูลและอ้างอิงพาร์ติชัน?

เรามาดูกฎข้อนี้ทีละข้อกัน

พาร์ติชันคืออะไร

ในระดับพื้นฐานที่สุด พาร์ติชันเป็นเพียงคอลเลกชันของขั้นตอนคิวรีอย่างน้อยหนึ่งรายการ พาร์ติชันที่ละเอียดที่สุดที่เป็นไปได้ (อย่างน้อยในการใช้งานปัจจุบัน) เป็นขั้นตอนเดียว บางครั้งพาร์ติชันที่ใหญ่ที่สุดอาจครอบคลุมหลายคิวรีได้ (เพิ่มเติมเกี่ยวกับเรื่องนี้ในภายหลัง)

ถ้าคุณไม่คุ้นเคยกับขั้นตอน คุณสามารถดูขั้นตอนเหล่านั้นทางด้านขวาของหน้าต่าง ตัวแก้ไข Power Query หลังจากเลือกคิวรีในบานหน้าต่าง ขั้นตอนที่ใช้ ขั้นตอนติดตามทุกสิ่งที่คุณทําเพื่อแปลงข้อมูลของคุณให้เป็นรูปร่างสุดท้าย

พาร์ติชันที่อ้างอิงถึงพาร์ติชันอื่น

เมื่อมีการประเมินคิวรีด้วยไฟร์วอลล์ ไฟร์วอลล์จะแบ่งคิวรีและการอ้างอิงทั้งหมดเป็นพาร์ติชัน (นั่นคือกลุ่มของขั้นตอน) เมื่อใดก็ตามที่พาร์ติชันหนึ่งอ้างอิงบางอย่างในพาร์ติชันอื่น ไฟร์วอลล์จะแทนที่การอ้างอิงด้วยการเรียกไปยังฟังก์ชันพิเศษที่เรียกว่าValue.Firewall กล่าวอีกนัยหนึ่งไฟร์วอลล์ไม่อนุญาตให้พาร์ติชันสามารถเข้าถึงซึ่งกันและกันได้โดยตรง การอ้างอิงทั้งหมดจะถูกแก้ไขเพื่อให้ผ่านไฟร์วอลล์ คิดว่าไฟร์วอลล์เป็นเกทเตอร์ พาร์ติชันที่อ้างอิงพาร์ติชันอื่นต้องได้รับสิทธิ์ไฟร์วอลล์ในการดําเนินการดังกล่าว และไฟร์วอลล์จะควบคุมว่าจะอนุญาตให้มีข้อมูลที่อ้างอิงลงในพาร์ติชันหรือไม่

ทั้งหมดนี้อาจดูเป็นนามธรรมที่สวยดังนั้นเรามาดูตัวอย่างกัน

สมมติว่าคุณมีคิวรีที่เรียกว่า พนักงาน ซึ่งดึงข้อมูลบางอย่างจากฐานข้อมูล SQL สมมติว่าคุณมีคิวรีอื่น (EmployeesReference) ซึ่งเพียงแค่อ้างอิงถึงพนักงาน

shared Employees = let
    Source = Sql.Database(…),
    EmployeesTable = …
in
    EmployeesTable;

shared EmployeesReference = let
    Source = Employees
in
    Source;

คิวรีเหล่านี้จะแบ่งออกเป็นสองพาร์ติชัน: หนึ่งสําหรับคิวรี Employees และอีกหนึ่งสําหรับคิวรี EmployeesReference (ซึ่งจะอ้างอิงพาร์ติชัน Employees) เมื่อประเมินด้วยไฟร์วอลล์บน คิวรีเหล่านี้จะถูกเขียนใหม่เช่นนั้น:

shared Employees = let
    Source = Sql.Database(…),
    EmployeesTable = …
in
    EmployeesTable;

shared EmployeesReference = let
    Source = Value.Firewall("Section1/Employees")
in
    Source;

โปรดสังเกตว่าการอ้างอิงอย่างง่ายไปยังคิวรี พนักงาน ถูกแทนที่ด้วยการเรียก ไปยัง Value.Firewallซึ่งให้ชื่อเต็มของคิวรี พนักงาน

เมื่อประเมิน EmployeesReference การเรียก ไปยัง Value.Firewall("Section1/Employees") จะถูกสกัดกั้นโดยไฟร์วอลล์ ซึ่งตอนนี้มีโอกาสในการควบคุมว่า (และวิธีการ) โฟลว์ข้อมูลที่ร้องขอไปยังพาร์ติชัน EmployeesReference หรือไม่ ซึ่งสามารถทําสิ่งต่าง ๆ ได้หลายวิธี: ปฏิเสธคําขอ บัฟเฟอร์ข้อมูลที่ร้องขอ (ซึ่งจะป้องกันไม่ให้มีการพับไปยังแหล่งข้อมูลต้นฉบับเพิ่มเติม) และอื่น ๆ

นี่คือวิธีที่ไฟร์วอลล์รักษาการควบคุมการไหลของข้อมูลระหว่างพาร์ติชัน

พาร์ติชันที่เข้าถึงแหล่งข้อมูลโดยตรง

สมมติว่าคุณกําหนดคิวรี 1 ด้วยขั้นตอนเดียว (โปรดทราบว่าคิวรีแบบขั้นตอนเดียวนี้สอดคล้องกับพาร์ติชันไฟร์วอลล์หนึ่งพาร์ติชัน) และขั้นตอนเดียวนี้เข้าถึงแหล่งข้อมูลสองแหล่ง: ตารางฐานข้อมูล SQL และไฟล์ CSV ไฟร์วอลล์จัดการกับสิ่งนี้ได้อย่างไรเนื่องจากไม่มีการอ้างอิงพาร์ติชันและดังนั้นจึงไม่มีการเรียก Value.Firewall ให้สกัดกั้น? เรามาทบทวนกฎที่ระบุไว้ก่อนหน้านี้:

  • พาร์ติชันอาจเข้าถึงแหล่งข้อมูลที่เข้ากันได้ หรืออ้างอิงพาร์ติชันอื่น ๆ แต่ไม่ใช่ทั้งสองอย่าง

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

จะเกิดอะไรขึ้นถ้าคุณพยายามเข้าถึงแหล่งข้อมูลที่เข้ากันไม่ได้ในพาร์ติชันเดียวกัน

Formula.Firewall: Query 'Query1' (step 'Source') is accessing data sources that have privacy levels which cannot be used together. Please rebuild this data combination.

หวังว่าคุณจะเข้าใจหนึ่งในข้อความแสดงข้อผิดพลาดที่แสดงไว้ที่จุดเริ่มต้นของบทความนี้ได้ดียิ่งขึ้น

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

ทําไมไม่ทําทั้งสองอย่าง

สมมติว่าคุณกําหนดคิวรีด้วยขั้นตอนหนึ่ง (ซึ่งจะสอดคล้องกับพาร์ติชันหนึ่ง) ที่เข้าถึงคิวรีอื่น ๆ สองรายการ (นั่นคือพาร์ติชันอื่นสองพาร์ติชัน) จะเกิดอะไรขึ้นถ้าคุณต้องการในขั้นตอนเดียวกันเพื่อเข้าถึงฐานข้อมูล SQL โดยตรงหรือไม่ ทําไมพาร์ติชันจึงไม่สามารถอ้างอิงพาร์ติชันอื่น ๆ และเข้าถึงแหล่งข้อมูลที่เข้ากันได้โดยตรง?

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

ดังนั้นจะเกิดอะไรขึ้นถ้าพาร์ติชันพยายามอ้างอิงพาร์ติชันอื่น ๆ และเข้าถึงแหล่งข้อมูลโดยตรง?

Formula.Firewall: Query 'Query1' (step 'Source') references other queries or steps, so it may not directly access a data source. Please rebuild this data combination.

ในตอนนี้ คุณหวังว่าจะเข้าใจข้อความแสดงข้อผิดพลาดอื่นๆ ที่แสดงอยู่ที่ส่วนเริ่มต้นของบทความนี้ได้ดียิ่งขึ้น

พาร์ติชันในเชิงลึก

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

ดังนั้นคิวรีจะได้รับการแบ่งพาร์ติชันอย่างไร

ส่วนนี้อาจเป็นสิ่งสําคัญที่สุดสําหรับการทําความเข้าใจสาเหตุที่คุณเห็นข้อผิดพลาดของไฟร์วอลล์ และทําความเข้าใจวิธีการแก้ไขปัญหาดังกล่าว (ถ้าเป็นไปได้)

นี่คือข้อมูลสรุประดับสูงของตรรกะการแบ่งพาร์ติชัน

  • การแบ่งพาร์ติชันเริ่มต้น
    • สร้างพาร์ติชันสําหรับแต่ละขั้นตอนในแต่ละคิวรี
  • ระยะคงที่
    • ระยะนี้ไม่ขึ้นอยู่กับผลลัพธ์การประเมิน แต่จะขึ้นอยู่กับวิธีการจัดโครงสร้างคิวรี
      • การตัดแต่งพารามิเตอร์
        • ตัดแต่งพาร์ติชันพารามิเตอร์ esque นั่นคือพาร์ติชันใดก็ตามที่:
          • ไม่อ้างอิงพาร์ติชันอื่น
          • ไม่ประกอบด้วยการเรียกฟังก์ชันใดๆ
          • ไม่ใช่วงจร (นั่นคือไม่ได้อ้างอิงถึงตัวเอง)
        • โปรดทราบว่า "ลบ" พาร์ติชันอย่างมีประสิทธิภาพรวมอยู่ในพาร์ติชันอื่น ๆ ที่อ้างอิง
        • การตัดแต่งพาร์ติชันพารามิเตอร์ช่วยให้การอ้างอิงพารามิเตอร์ที่ใช้ภายในการเรียกใช้ฟังก์ชันแหล่งข้อมูล (ตัวอย่างเช่น Web.Contents(myUrl)) ทํางานแทนการขว้าง "พาร์ติชันไม่สามารถอ้างอิงแหล่งข้อมูลและขั้นตอนอื่น ๆ"
      • การจัดกลุ่ม (คงที่)
        • มีการผสานพาร์ติชันในลําดับการขึ้นต่อกันด้านล่าง ในพาร์ติชันที่ผสานผลลัพธ์ รายการต่อไปนี้จะต้องแยกกัน:
          • พาร์ติชันในคิวรีที่แตกต่างกัน
          • พาร์ติชันที่ไม่ได้อ้างอิงพาร์ติชันอื่น ๆ (และได้รับอนุญาตให้เข้าถึงแหล่งข้อมูล)
          • พาร์ติชันที่อ้างอิงถึงพาร์ติชันอื่น ๆ (และ จึงถูกห้ามไม่ให้เข้าถึงแหล่งข้อมูล)
  • ระยะแบบไดนามิก
    • ระยะนี้ขึ้นอยู่กับผลลัพธ์การประเมิน รวมถึงข้อมูลเกี่ยวกับแหล่งข้อมูลที่เข้าถึงโดยพาร์ติชันต่างๆ
    • การตัดแต่ง
      • ตัดแต่งพาร์ติชันที่ตรงตามความต้องการต่อไปนี้ทั้งหมด:
        • ไม่สามารถเข้าถึงแหล่งข้อมูลใด ๆ
        • ไม่อ้างอิงพาร์ติชันใดๆ ที่เข้าถึงแหล่งข้อมูล
        • ไม่ใช่วงจร
    • การจัดกลุ่ม (แบบไดนามิก)
      • ในตอนนี้พาร์ติชันที่ไม่จําเป็นได้ถูกตัดแต่งแล้ว ให้ลองสร้างพาร์ติชันแหล่งข้อมูลที่มีขนาดใหญ่ที่สุดเท่าที่เป็นไปได้ ซึ่งสามารถทําได้โดยการผสานพาร์ติชันโดยใช้กฎเดียวกันที่อธิบายไว้ในขั้นตอนการจัดกลุ่มแบบคงที่ด้านบน

ทั้งหมดนี้หมายความว่าอย่างไร

ลองทําตามตัวอย่างเพื่อแสดงตัวอย่างวิธีการทํางานของตรรกะที่ซับซ้อนที่วางไว้ด้านบน

นี่คือตัวอย่างสถานการณ์ ซึ่งเป็นการผสานแฟ้มข้อความ (ผู้ติดต่อ) ที่มีฐานข้อมูล SQL (พนักงาน) อย่างเป็นธรรม โดยที่เซิร์ฟเวอร์ SQL เป็นพารามิเตอร์ (DbServer)

คิวรีสามรายการ

นี่คือรหัส M สําหรับคิวรีสามรายการที่ใช้ในตัวอย่างนี้

shared DbServer = "montegoref6" meta [IsParameterQuery=true, Type="Text", IsParameterQueryRequired=true];
shared Contacts = let

    Source = Csv.Document(File.Contents("C:\contacts.txt"),[Delimiter="   ", Columns=15, Encoding=1252, QuoteStyle=QuoteStyle.None]),

    #"Promoted Headers" = Table.PromoteHeaders(Source, [PromoteAllScalars=true]),

    #"Changed Type" = Table.TransformColumnTypes(#"Promoted Headers",{{"ContactID", Int64.Type}, {"NameStyle", type logical}, {"Title", type text}, {"FirstName", type text}, {"MiddleName", type text}, {"LastName", type text}, {"Suffix", type text}, {"EmailAddress", type text}, {"EmailPromotion", Int64.Type}, {"Phone", type text}, {"PasswordHash", type text}, {"PasswordSalt", type text}, {"AdditionalContactInfo", type text}, {"rowguid", type text}, {"ModifiedDate", type datetime}})

in

    #"Changed Type";
shared Employees = let

    Source = Sql.Databases(DbServer),

    AdventureWorks = Source{[Name="AdventureWorks"]}[Data],

    HumanResources_Employee = AdventureWorks{[Schema="HumanResources",Item="Employee"]}[Data],

    #"Removed Columns" = Table.RemoveColumns(HumanResources_Employee,{"HumanResources.Employee(EmployeeID)", "HumanResources.Employee(ManagerID)", "HumanResources.EmployeeAddress", "HumanResources.EmployeeDepartmentHistory", "HumanResources.EmployeePayHistory", "HumanResources.JobCandidate", "Person.Contact", "Purchasing.PurchaseOrderHeader", "Sales.SalesPerson"}),

    #"Merged Queries" = Table.NestedJoin(#"Removed Columns",{"ContactID"},Contacts,{"ContactID"},"Contacts",JoinKind.LeftOuter),

    #"Expanded Contacts" = Table.ExpandTableColumn(#"Merged Queries", "Contacts", {"EmailAddress"}, {"EmailAddress"})

in

    #"Expanded Contacts";

นี่คือมุมมองระดับสูงกว่า ที่แสดงการขึ้นต่อกัน

กล่องโต้ตอบการขึ้นต่อกันของคิวรี

มาแบ่งพาร์ติชันกัน

เรามาย่อ/ขยายสักเล็กน้อยและรวมขั้นตอนในรูปภาพและเริ่มเดินผ่านตรรกะการแบ่งพาร์ติชัน นี่คือไดอะแกรมของคิวรีสามรายการ ที่แสดงพาร์ติชันไฟร์วอลล์เริ่มต้นเป็นสีเขียว โปรดสังเกตว่าแต่ละขั้นตอนเริ่มต้นในพาร์ติชันของตนเอง

พาร์ติชันไฟร์วอลล์เริ่มต้น

ถัดไป เราจะตัดแต่งพาร์ติชันพารามิเตอร์ ดังนั้น DbServer จะถูกรวมโดยนัยในพาร์ติชันต้นทาง

พาร์ติชันไฟร์วอลล์ที่ตัดแต่งแล้ว

ในตอนนี้เราทําการจัดกลุ่มแบบคงที่ ซึ่งจะรักษาการแยกระหว่างพาร์ติชันในคิวรีที่แยกต่างหาก (หมายเหตุสําหรับอินสแตนซ์ที่สองขั้นตอนสุดท้ายของพนักงานจะไม่ได้รับการจัดกลุ่มตามขั้นตอนของผู้ติดต่อ) และระหว่างพาร์ติชันที่อ้างอิงพาร์ติชันอื่น ๆ (เช่น สองขั้นตอนสุดท้ายของพนักงาน) และส่วนที่ไม่ได้รวม (เช่น สามขั้นตอนแรกของพนักงาน)

โพสต์พาร์ติชันไฟร์วอลล์การจัดกลุ่มแบบคงที่

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

มาเสแสร้งกัน

เพื่อให้ได้ภาพประกอบ แต่มาดูกันว่าจะเกิดอะไรขึ้นถ้าคิวรี Contacts แทนที่จะมาจากไฟล์ข้อความ โค้ดแบบฮาร์ดโค้ดใน M (อาจผ่าน กล่องโต้ตอบป้อนข้อมูล )

ในกรณีนี้ คิวรีผู้ติดต่อจะไม่เข้าถึงแหล่งข้อมูลใด ๆ ดังนั้นมันจะได้รับการตัดแต่งในช่วงแรกของระยะแบบไดนามิก

พาร์ติชันไฟร์วอลล์หลังจากการตัดแต่งขั้นตอนแบบไดนามิก

เมื่อลบพาร์ติชันผู้ติดต่อแล้ว สองขั้นตอนสุดท้ายของพนักงานจะไม่อ้างอิงพาร์ติชันใด ๆ อีกต่อไป ยกเว้นพาร์ติชันที่มีสามขั้นตอนแรกของพนักงาน ดังนั้น จะมีการจัดกลุ่มสองพาร์ติชัน

พาร์ติชันผลลัพธ์จะมีลักษณะดังนี้

พาร์ติชันไฟร์วอลล์ขั้นสุดท้าย

ตัวอย่าง: การส่งผ่านข้อมูลจากแหล่งข้อมูลหนึ่งไปยังอีกแหล่งข้อมูลหนึ่ง

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

ลองจินตนาการว่าคุณต้องการค้นหาชื่อบริษัทจากบริการ Northwind OData จากนั้นใช้ชื่อบริษัทเพื่อทําการค้นหาใน Bing

ก่อนอื่น คุณสร้าง การสอบถาม Company เพื่อดึงข้อมูลชื่อบริษัท

let
    Source = OData.Feed("https://services.odata.org/V4/Northwind/Northwind.svc/", null, [Implementation="2.0"]),
    Customers_table = Source{[Name="Customers",Signature="table"]}[Data],
    CHOPS = Customers_table{[CustomerID="CHOPS"]}[CompanyName]
in
    CHOPS

ถัดไป คุณสร้าง คิวรีการค้นหา ที่อ้างอิง ถึงบริษัท และส่งผ่านไปยัง Bing

let
    Source = Text.FromBinary(Web.Contents("https://www.bing.com/search?q=" & Company))
in
    Source

ในตอนนี้ คุณพบปัญหา การประเมิน การค้นหา สร้างข้อผิดพลาดของไฟร์วอลล์

Formula.Firewall: Query 'Search' (step 'Source') references other queries or steps, so it may not directly access a data source. Please rebuild this data combination.

ทั้งนี้เนื่องจากขั้นตอนแหล่งที่มาของ การค้นหา จะอ้างอิงแหล่งข้อมูล (bing.com) และยังอ้างอิงคิวรี/พาร์ติชันอื่น (บริษัท) ซึ่งจะละเมิดกฎที่กล่าวถึงข้างต้น ("พาร์ติชันอาจเข้าถึงแหล่งข้อมูลที่เข้ากันได้ หรืออ้างอิงพาร์ติชันอื่น ๆ แต่ไม่ใช่ทั้งสองพาร์ติชัน")

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

หากต้องการแก้ไขข้อผิดพลาดโดยไม่ปิดใช้งานไฟร์วอลล์ คุณสามารถรวม Company และ Search ไว้ในคิวรีเดียวได้ ดังนี้:

let
    Source = OData.Feed("https://services.odata.org/V4/Northwind/Northwind.svc/", null, [Implementation="2.0"]),
    Customers_table = Source{[Name="Customers",Signature="table"]}[Data],
    CHOPS = Customers_table{[CustomerID="CHOPS"]}[CompanyName],
    Search = Text.FromBinary(Web.Contents("https://www.bing.com/search?q=" & CHOPS))
in
    Search

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

แค่ห่อ

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