Partial Records were indeed introduced in Business Central 2020 Release Wave 2 (version 17.0), and they represent a significant optimization feature for AL development.
What Are Partial Records?
Partial Records is a performance optimization feature that allows you to load only a subset of fields from a table instead of all fields when using the FindSet(), FindFirst(), FindLast(), and Get() methods.
Basic Syntax:
procedure ProcessCustomers()
var
Customer: Record Customer;
begin
// OLD WAY - loads ALL fields
if Customer.FindSet() then
repeat
// Processes all fields
until Customer.Next() = 0;
// NEW WAY with Partial Records - loads only specified fields
Customer.SetLoadFields(Customer."No.", Customer.Name, Customer.Blocked);
if Customer.FindSet() then
repeat
// Only has access to "No.", Name, and Blocked fields
if Customer.Blocked = Customer.Blocked::" " then
Message('Customer %1: %2', Customer."No.", Customer.Name);
until Customer.Next() = 0;
end;Key Benefits and Use Cases
1. Performance Optimization
procedure GetCustomerNames()
var
Customer: Record Customer;
begin
// Only loads 2 fields instead of 100+ fields in the Customer table
Customer.SetLoadFields(Customer."No.", Customer.Name);
if Customer.FindSet() then
repeat
// Much faster database retrieval
ProcessCustomerName(Customer.Name);
until Customer.Next() = 0;
end;2. Reduced Network Traffic
- Especially important for SaaS environments
- Minimizes data transfer between database and application server
3. Memory Efficiency
procedure CheckBlockedCustomers()
var
Customer: Record Customer;
Counter: Integer;
begin
// Only load the essential fields for this specific task
Customer.SetLoadFields(Customer.Blocked, Customer."No.");
Customer.SetRange(Blocked, Customer.Blocked::All);
if Customer.FindSet() then
repeat
Counter += 1;
until Customer.Next() = 0;
Message('Total blocked customers: %1', Counter);
end;Important Rules and Limitations
Field Access Restrictions:
procedure ExampleWithLimitations()
var
Customer: Record Customer;
begin
Customer.SetLoadFields(Customer."No.", Customer.Name);
if Customer.FindSet() then
repeat
// ✅ THIS WORKS - field is loaded
Message(Customer.Name);
// ❌ THIS CAUSES RUNTIME ERROR - field not loaded
// Message(Customer."Phone No."); // ERROR!
until Customer.Next() = 0;
end;Multiple SetLoadFields Calls:
procedure MultipleLoadFields()
var
Customer: Record Customer;
begin
// Only the LAST call to SetLoadFields is effective
Customer.SetLoadFields(Customer."No."); // ❌ Ignored
Customer.SetLoadFields(Customer.Name); // ❌ Ignored
Customer.SetLoadFields(Customer.Blocked); // ✅ This one is used
if Customer.FindSet() then
// Only Customer.Blocked field is loaded
end;Combining Fields:
procedure CombineFields()
var
Customer: Record Customer;
begin
// Load multiple fields in one call
Customer.SetLoadFields(Customer."No.", Customer.Name, Customer."Balance (LCY)");
if Customer.FindSet() then
repeat
// All specified fields are accessible
ProcessCustomerData(Customer."No.", Customer.Name, Customer."Balance (LCY)");
until Customer.Next() = 0;
end;Best Practices
1. Use in Loops with Limited Field Needs
procedure UpdateCustomerStatus()
var
Customer: Record Customer;
begin
// Only load fields needed for the status update
Customer.SetLoadFields(Customer."No.", Customer.Blocked, Customer."Last Date Modified");
if Customer.FindSet() then
repeat
if ShouldUpdateStatus(Customer) then
UpdateCustomerStatus(Customer."No.");
until Customer.Next() = 0;
end;2. Avoid in Complex Business Logic
procedure ComplexProcessing()
var
Customer: Record Customer;
begin
// Don't use Partial Records if you might need various fields
// Customer.SetLoadFields(...); // ❌ Don't limit fields here
if Customer.FindSet() then
repeat
// This procedure might need different fields based on conditions
if ConditionA then
UseFieldA(Customer);
else if ConditionB then
UseFieldB(Customer);
until Customer.Next() = 0;
end;3. Ideal for Reporting and Statistics
procedure CalculateCustomerStatistics()
var
Customer: Record Customer;
TotalBalance: Decimal;
begin
// Perfect use case - only need specific fields for calculations
Customer.SetLoadFields(Customer."Balance (LCY)", Customer."Customer Posting Group");
if Customer.FindSet() then
repeat
TotalBalance += Customer."Balance (LCY)";
until Customer.Next() = 0;
Message('Total customer balance: %1', TotalBalance);
end;Performance Impact Example
Consider a Customer table with 150 fields:
Without Partial Records:
- Loads 150 fields × 10,000 records = 1,500,000 field values
- Significant memory and network usage
With Partial Records (loading 3 fields):
- Loads 3 fields × 10,000 records = 30,000 field values
- 98% reduction in data transfer!
Summary
Partial Records, introduced in BC v17, provide:
- ✅ Major performance improvements for data retrieval
- ✅ Reduced memory consumption
- ✅ Minimized network traffic (crucial for cloud)
- ✅ Cleaner code intent – explicitly declaring data needs
Important Considerations:
- ❌ Runtime errors if accessing non-loaded fields
- ❌ Only the last
SetLoadFields()call is effective - ❌ Not suitable for all scenarios (be strategic)
This feature represents Microsoft’s ongoing commitment to optimizing Business Central performance, especially important as systems grow larger and more complex in enterprise environments.
