Microsoft Fabric stores and serves data through Lakehouses, Warehouses, Eventhouses, semantic models, files, and APIs. ‘fabricQueryR’ helps you bring that data into your local R session for analysis, visualization, and reporting. For most everyday tasks, the result is a tibble (a modern R data frame).
The best method depends on where the data lives and whether you need a whole table or a filtered result. Start with a small read and let Fabric filter the data when possible. Move to Arrow streaming or Spark only when the data is too large for local memory or the transformation needs distributed computing. This guide compares the common methods in that order.
Choose a reading method
| Your source or goal | Start with | Why |
|---|---|---|
| Warehouse, SQL Database, or a SQL-shaped Lakehouse query |
item$sql_query() (fabric_sql_query()) |
Filter and summarize on the server with familiar SQL |
| One Lakehouse Delta table |
lakehouse$read_table()
(fabric_lakehouse_read_table()) |
Read a table without writing SQL |
| One Warehouse table |
warehouse$read_table()
(fabric_warehouse_read_table()) |
Read a table by name without writing SQL |
| Eventhouse table or KQL result |
kql_database$read_table()
(fabric_kql_read_table()) or $query()
(fabric_kql_query()) |
Use the Eventhouse query engine |
| Power BI/Fabric semantic model |
model$dax_query()
(fabric_pbi_dax_query()) |
Use model relationships and measures |
| CSV, Parquet, or Arrow file in OneLake |
lakehouse$onelake_read_file()
(fabric_onelake_read_file()) |
Read the file itself |
| API for GraphQL |
api$query() (fabric_graphql_query()) |
Request the fields exposed by the API |
| A transformation that genuinely needs Spark |
lakehouse$livy_query()
(fabric_livy_query()) |
Run distributed code in Fabric |
SQL is a good default for relational data because Fabric does the filtering and R receives only the rows you need. A direct table reader is simpler when you want one table and do not need joins or grouping.
Discover the data source once
Discovery returns read-only R6 objects. They carry the IDs,
connection details, and credential needed by their read methods. Read
service fields such as $displayName and $id
directly:
library(fabricQueryR)
workspaces <- fabric_workspaces()
matches <- Filter(
\(x) identical(x$displayName, "Analytics workspace"),
workspaces
)
stopifnot(length(matches) == 1L)
workspace <- matches[[1L]]
lakehouse <- workspace$lakehouses()[[1L]]
warehouse <- workspace$warehouses()[[1L]]
kql_database <- workspace$kql_databases()[[1L]]
model <- workspace$semantic_models()[[1L]]The workspace methods above correspond to
fabric_lakehouses(), fabric_warehouses(),
fabric_kql_databases(), and
fabric_semantic_models().
Your workspace does not need to contain every item type. Discover only the source used by your workflow.
Read with SQL
Use an item’s $sql_query() method
(fabric_sql_query()) for one read-only SELECT
query. It opens and closes the connection for you and returns a
tibble:
recent_orders <- warehouse$sql_query(
sql = paste(
"SELECT TOP 100 order_id, order_date, amount",
"FROM dbo.orders",
"WHERE order_date >= ?",
"ORDER BY order_date DESC"
),
params = list(as.Date("2026-01-01"))
)
head(recent_orders)Put changing values in params rather than pasting them
into the SQL text. This handles quoting safely. Use
$sql_connect() (fabric_sql_connect()) and
normal ‘DBI’ functions when several queries should share one
connection:
con <- warehouse$sql_connect()
on.exit(DBI::dbDisconnect(con), add = TRUE)
DBI::dbListTables(con)
orders <- DBI::dbGetQuery(con, "SELECT TOP 100 * FROM dbo.orders")The default SQL backend uses Microsoft ODBC Driver 18 for SQL Server.
See ?fabric_sql_connect for the ODBC and ADBC setup
choices.
Read one table without writing a query
Lakehouse and Warehouse table readers accept a table name and can
limit the data before it enters R. The $read_table()
methods call fabric_lakehouse_read_table() and
fabric_warehouse_read_table(), respectively:
lakehouse_rows <- lakehouse$read_table(
table = "orders",
columns = c("order_id", "order_date", "amount"),
limit = 100L
)
warehouse_rows <- warehouse$read_table(
table = "orders",
schema = "dbo",
limit = 100L
)Use lakehouse$tables()
(fabric_lakehouse_tables()) when you are unsure which
Lakehouse tables or schemas are available.
Read Eventhouse data
An Eventhouse is optimized for event, log, and time-series data. Its
query language is KQL. Read a whole table by name with
$read_table() (fabric_kql_read_table()):
events <- kql_database$read_table(
table = "Events",
limit = 100L
)Use $query() (fabric_kql_query()) when
Fabric should filter or summarize the events first:
daily_events <- kql_database$query(
query = paste(
"Events",
"| where observed_at >= ago(7d)",
"| summarize event_count = count() by bin(observed_at, 1d)",
"| order by observed_at asc"
)
)Query a semantic model with DAX
A semantic model is a dataset ready for reporting, commonly used in
Power BI. Query it with $dax_query()
(fabric_pbi_dax_query()) and DAX (Data Analysis
Expressions):
sales_by_region <- model$dax_query(
dax = paste(
"EVALUATE",
"SUMMARIZECOLUMNS(",
" 'Region'[Region],",
" \"Total Sales\", [Total Sales]",
")"
)
)The Semantic Models vignette shows more things you can do with semantic models, like refreshing their data.
Read a OneLake file
Use the file reader when the file itself is the data contract. Paths
in a Lakehouse usually begin with Files/. The
$onelake_read_file() method calls
fabric_onelake_read_file():
orders_file <- lakehouse$onelake_read_file(
path = "Files/exports/orders.parquet"
)CSV, Parquet, and Arrow IPC files can become R or Arrow objects.
Other file types can be downloaded as raw bytes or to disk. Use a
Lakehouse table reader, not a file reader, for managed data below
Tables/.
Read through GraphQL or Spark
GraphQL is useful when a Fabric API item exposes a purpose-built selection of fields:
api <- workspace$graphql_apis()[[1L]]
response <- api$query(
query = "{ products { items { id name category } } }"
)
products <- response$data$products$itemsUse Working with GraphQL
for schema inspection and pagination. $graphql_apis() is
the workspace method for fabric_graphql_apis().
Spark is the later choice for distributed transformations, Spark-only data formats, or logic already written for Spark:
result <- lakehouse$livy_query(
kind = "sql",
code = "SELECT category, count(*) AS n FROM orders GROUP BY category"
)
counts <- result$output$parsedSpark has startup cost. Prefer SQL or a direct reader for a small, ordinary table read.
Scale up with Arrow streams
If a selected result is larger than your computer’s working memory, process it as a stream instead of collecting it all at once.
Several readers accept result = "arrow_stream". This can
be used with the ‘arrow’ R package to read the data in batches. Here
$read_table() calls
fabric_lakehouse_read_table():
stream <- lakehouse$read_table(
table = "large_orders",
result = "arrow_stream"
)
reader <- arrow::as_record_batch_reader(stream)
orders <- reader$read_table()
reader$Close()Close an Arrow reader after use. For disk-backed OneLake Delta
streams, this also deletes the staged temporary file; when consuming one
directly through ‘nanoarrow’, call stream[["release"]]()
instead.
See the ‘arrow’ R package for more information on working with Arrow streams and record batches.