แชร์ผ่าน


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

Note

ขณะนี้ระดับความเป็นส่วนตัวไม่พร้อมใช้งานในกระแสข้อมูล 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 มาจากข้อเท็จจริงที่ว่า Power Query สามารถแปลงการดําเนินการที่ผู้ใช้ดําเนินการผ่านส่วนติดต่อผู้ใช้เป็น SQL ที่ซับซ้อนหรือภาษาแหล่งข้อมูลแบ็กเอนด์อื่นๆ โดยที่ผู้ใช้ไม่จําเป็นต้องรู้ภาษาดังกล่าว ผู้ใช้จะได้รับประโยชน์ด้านประสิทธิภาพของการดําเนินการแหล่งข้อมูลดั้งเดิม ด้วยความง่ายในการใช้งาน UI ที่แหล่งข้อมูลทั้งหมดสามารถแปลงได้โดยใช้ชุดคําสั่งทั่วไป

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

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

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

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

ขั้นตอนการทํางาน

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

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

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

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

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

ลองแยกย่อยและดูกฎก่อนหน้านี้ทีละชิ้น

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

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

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

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

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

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

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

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 หรือไม่ สามารถทําสิ่งต่างๆ ได้หลายอย่าง: ปฏิเสธคําขอ บัฟเฟอร์ข้อมูลที่ร้องขอ (ซึ่งป้องกันไม่ให้เกิดการพับไปยังแหล่งข้อมูลเดิม) และอื่นๆ

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

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

สมมติว่าคุณกําหนดคิวรี Query1 ด้วยขั้นตอนเดียว (โปรดทราบว่าคิวรีขั้นตอนเดียวนี้สอดคล้องกับพาร์ติชันไฟร์วอลล์หนึ่งพาร์ติชัน) และขั้นตอนเดียวนี้เข้าถึงแหล่งข้อมูลสองแหล่ง: ตารางฐานข้อมูล 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.

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

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

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

แล้วแบบสอบถามจะถูกแบ่งพาร์ติชันได้อย่างไร?

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

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

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

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

ลองดูตัวอย่างเพื่อแสดงให้เห็นว่าตรรกะที่ซับซ้อนที่วางไว้ก่อนหน้านี้ทํางานอย่างไร

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

คําถามทั้งสาม

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

shared DbServer = "MySqlServer" 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 จึงรวมอยู่ในพาร์ติชันต้นทางโดยปริยาย

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

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

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

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

มาแกล้งทําเป็นกันเถอะ

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

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

แผนภาพแสดงพาร์ติชันไฟร์วอลล์หลังจากการตัดแต่งเฟสแบบไดนามิก

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

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

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

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

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

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

ขั้นแรก คุณสร้างแบบสอบถาม บริษัท เพื่อเรียกชื่อบริษัท

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) และยังอ้างอิงแบบสอบถาม/พาร์ติชันอื่น (บริษัท) เป็นการละเมิดกฎที่กล่าวถึงก่อนหน้านี้ ("พาร์ติชันสามารถเข้าถึงแหล่งข้อมูลที่เข้ากันได้ หรืออ้างอิงพาร์ติชันอื่น ๆ แต่ไม่ใช่ทั้งสองอย่าง")

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

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

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

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

นั่นคือบทสรุป

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