Reading data from Fabric
Pass values into queries and read totals for reports.
This page will show you how to read data from Microsoft Fabric in Python:
- Passing values into a query
- Reading totals for a report
Under the hood, conn.query sends T-SQL to the lakehouse's SQL analytics endpoint, the same one the SQL query view in Fabric uses, and returns the rows as a list of dicts.
Connection and IDs
The app registration, the Fabric connection in the Zato Dashboard, and the workspace and lakehouse IDs are the same as in the tutorial, so set them up as described there first.
Passing values into a query
In the tutorial, the location and the status were part of the SQL itself. In this example, a caller of the service sends a location and a date range, and the service returns the occupancy of that location for those days.
The service below will:
- Take the location and the two dates from its input
- Hand them to the query through
paramsrather than glue them into the SQL - Return the rows to the caller
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class GetOccupancy(Service):
name = 'fabric.get-occupancy'
input = 'location', 'date_from', 'date_to'
def handle(self):
# The two IDs from the tutorial ..
workspace_id = '262ddd3d-3d0d-4495-b80f-6dddda1e23a1'
lakehouse_id = '73811955-064d-481a-a7e9-f9c563124f9e'
# .. the query to run ..
sql = """
select location, as_of, occupied_beds, available_beds
from occupancy
where location = :location
and as_of between :date_from and :date_to
order by as_of
"""
# .. the values, taken from our input ..
params = {
'location': self.request.input.location,
'date_from': self.request.input.date_from,
'date_to': self.request.input.date_to,
}
# .. get a Fabric connection ..
conn = self.microsoft.fabric['Zato Fabric']
# .. run the query with the values ..
rows = conn.query(workspace_id, lakehouse_id, sql, params)
# .. and return the rows to our caller.
self.response.payload = rows
After invoking the service with Riverside, 2026-08-30 and 2026-08-31 you'll see:
[{"location": "Riverside", "as_of": "2026-08-30", "occupied_beds": 95, "available_beds": 25},
{"location": "Riverside", "as_of": "2026-08-31", "occupied_beds": 96, "available_beds": 24}]
About params:
- Each
:namemarker in the SQL needs a key of that name in the dict - Dates and times go in as text in ISO format, e.g.
2026-08-31or2026-08-31 09:00:00 - You should not use Python f-strings for the values, because a value glued into the SQL becomes part of the statement, so a caller could sends
'; drop table occupancy --and this would lead to an SQL injection attack
Reading totals for a report
In this example, on the first day of each month, a scheduled service reads last month's invoices grouped by insurer, and the totals are returned to callers for further processing, e.g. to be sent over email.
The service below will:
- Work out where last month begins and ends
- Run a query that groups the rows and sums them up
- Return the totals
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class MonthlyInvoiceSummary(Service):
name = 'fabric.monthly-invoice-summary'
def handle(self):
# The two IDs from the tutorial ..
workspace_id = '262ddd3d-3d0d-4495-b80f-6dddda1e23a1'
lakehouse_id = '73811955-064d-481a-a7e9-f9c563124f9e'
# .. get our time range ..
today = self.time.today(format=False)
this_month_start = today.floor('month')
last_month_start = this_month_start.shift(months=-1)
# .. for later use ..
params = {
'range_start': last_month_start.format('YYYY-MM-DD'),
'range_end': this_month_start.format('YYYY-MM-DD'),
}
# .. our query to run ..
sql = """
select
insurer,
count(*) as invoices,
round(sum(amount), 2) as invoiced,
round(sum(
case when status = 'paid' then amount else 0 end
), 2) as paid
from invoices
where sent_at >= :range_start
and sent_at < :range_end
group by insurer
order by insurer
"""
# .. get a Fabric connection ..
conn = self.microsoft.fabric['Zato Fabric']
# .. run the query ..
rows = conn.query(workspace_id, lakehouse_id, sql, params)
# .. and return the totals to our caller.
month = last_month_start.format('YYYY-MM')
self.response.payload = {'month': month, 'rows': rows}
After invoking the service you'll see:
{"month": "2026-08", "rows": [
{"insurer": "Cascade Health Plan", "invoices": 8, "invoiced": 14050.00, "paid": 0.00},
{"insurer": "Evergreen Assurance", "invoices": 8, "invoiced": 13750.00, "paid": 0.00},
{"insurer": "Pacific Mutual", "invoices": 8, "invoiced": 13450.00, "paid": 13450.00}
]}
See also
| Page | What it covers |
|---|---|
| Your first Fabric integration | The app registration, the connection and where the IDs come from |
| Writing data to Fabric | Writing the tables these services read |
| Fabric API - Queries | conn.query, conn.refresh_sql_endpoint and the Spark methods, with every parameter |