Entity API#

The Entity API provides object-oriented access to B-Fabric data with lazy-loading relationships and automatic caching. Access it through client.reader, which returns an EntityReader instance.

Reading Entities#

By URI#

Read entities by their B-Fabric URIs:

from bfabric import Bfabric

client = Bfabric.connect()
reader = client.reader

# Single entity
uri = "https://fgcz-bfabric.uzh.ch/bfabric/sample/show.html?id=123"
sample = reader.read_uri(uri)

# Multiple entities (mixed types)
uris = [
    "https://fgcz-bfabric.uzh.ch/bfabric/sample/show.html?id=123",
    "https://fgcz-bfabric.uzh.ch/bfabric/project/show.html?id=456",
]
entities = reader.read_uris(uris)  # Returns dict[URI, Entity]
EntityReader.read_uri(uri: EntityUri | str, *, expected_type: type[EntityT] = <class 'bfabric.entities.core.entity.Entity'>) EntityT | None

Read a single entity by its B-Fabric URI.

Args:

uri: B-Fabric URI of the entity (e.g., “https://…/sample/show.html?id=123”) expected_type: Entity class (e.g., Sample) for type validation and casting

Returns:

Entity object or None if not found

Raises:

ValueError: If URI is invalid or from a different B-Fabric instance TypeError: If entity exists but doesn’t match expected_type

EntityReader.read_uris(uris: ~collections.abc.Iterable[~bfabric.entities.core.uri.EntityUri | str], *, expected_type: type[~bfabric.entities.core.entity_reader.EntityT] = <class 'bfabric.entities.core.entity.Entity'>) dict[EntityUri, EntityT | None]

Read multiple entities by their URIs efficiently.

Entities are grouped by type and retrieved in batches to minimize API calls. Uses the cache stack if configured.

Args:

uris: Iterable of B-Fabric URIs (can be different entity types) expected_type: Entity class to validate and cast all results

Returns:

Dictionary mapping each input URI to its entity object (or None if not found)

Raises:

ValueError: If any URI is from a different B-Fabric instance

By ID#

Read entities by type and ID:

# Single entity
sample = reader.read_id(entity_type="sample", entity_id=123)

# Multiple entities of the same type
entities = reader.read_ids(entity_type="sample", entity_ids=[123, 456, 789])
EntityReader.read_id(entity_type: str, entity_id: int, bfabric_instance: str | None = None, *, expected_type: type[EntityT] = <class 'bfabric.entities.core.entity.Entity'>) EntityT | None

Read a single entity by its type and ID.

Args:

entity_type: B-Fabric entity type (e.g., “sample”, “project”) entity_id: Numeric ID of entity bfabric_instance: B-Fabric instance URL (defaults to client’s configured instance) expected_type: Entity class to validate and cast the result

Returns:

Entity object or None if not found

Raises:

ValueError: If instance doesn’t match the client’s configuration

EntityReader.read_ids(entity_type: str, entity_ids: list[int], bfabric_instance: str | None = None, *, expected_type: type[~bfabric.entities.core.entity_reader.EntityT] = <class 'bfabric.entities.core.entity.Entity'>) dict[EntityUri, EntityT | None]

Read multiple entities of the same type by their IDs.

Args:

entity_type: B-Fabric entity type (e.g., “sample”) entity_ids: List of numeric IDs bfabric_instance: B-Fabric instance URL (defaults to client’s configured instance) expected_type: Entity class to validate and cast all results

Returns:

Dictionary mapping entity URIs to their objects (or None if not found)

By Query#

Query entities with search criteria:

# Find samples by name
entities = reader.query(entity_type="sample", obj={"name": "MySample"}, max_results=100)
EntityReader.query(entity_type: str, obj: ApiRequestObjectType, bfabric_instance: str | None = None, max_results: int | None = 100) dict[EntityUri, Entity | None]

Query entities by search criteria and return them as Entity objects.

Combines client.read() with automatic entity instantiation and caching.

Args:

entity_type: B-Fabric entity type to query obj: Dictionary of search criteria (e.g., {"name": "MySample"}) bfabric_instance: B-Fabric instance URL (defaults to client’s configured instance) max_results: Maximum number of results to return (default: 100, None for all)

Returns:

Dictionary mapping entity URIs to their objects

Entity Objects#

When you read entities through the Entity API, you get Entity objects with typed properties:

Basic Properties#

sample = reader.read_id(entity_type="sample", entity_id=123)

# Entity identifier
print(sample.id)  # 123
print(sample.classname)  # "sample"
print(sample.bfabric_instance)  # "https://fgcz-bfabric.uzh.ch/bfabric/"

# Entity URI
uri = sample.uri
print(uri)  # EntityUri object

# Raw data dictionary
data = sample.data_dict

Accessing Data#

Entities support dictionary-like access to their data:

# Check if a field exists
if "name" in sample:
    name = sample["name"]

# Get a field with default
name = sample.get("name", "Unknown")

Relationships and References#

Entities can have relationships to other entities, accessed via the refs property. These are lazy-loaded, meaning they’re only fetched from B-Fabric when you first access them.

sample = reader.read_id(entity_type="sample", entity_id=123)

# Access a related project (one-to-one)
project = sample.refs.get("container")

# Access related workunits (one-to-many)
workunits = sample.refs.get("member")

Check if a reference is already loaded:

if sample.refs.is_loaded("container"):
    print("Project already loaded")

Custom Entity Classes#

bfabricPy provides custom entity classes for common types (e.g., Project, Sample, Workunit) which provide type-specific methods and properties:

from bfabric import Project

# Read as specific entity type
project = reader.read_id(entity_type="project", entity_id=123, expected_type=Project)

Current Limitations#

  1. Single B-Fabric Instance: Query operations only work with the client’s configured B-Fabric instance.

  2. URI Validation: URIs must match the client’s configured instance.

  3. None Returns: Methods return None when an entity is not found, rather than raising an exception.

Comparison to ResultContainer API#

If you find yourself needing any of the following, consider using ResultContainer API instead:

  • Working with raw dictionary data

  • Exporting directly to DataFrames without entity overhead

  • Simple queries without relationships

Entity-Specific Features#

For detailed information about specific entity types and their special features (like Dataset export methods, Workunit parameter access, Resource path methods), see Entity Features.