TSQL.APP File Management Training

Introduction to File Management in TSQL.APP

TSQL.APP offers robust built-in functionality for file management, allowing you to easily upload, store, categorize, and display files within your application. This training covers the key concepts, components, and best practices for effective file management in TSQL.APP.

Table of Contents

  1. Database Structure for Files
  2. File Functions and Stored Procedures
  3. File Uploads in Forms
  4. Managing File Categories
  5. Practical Examples
  6. Common Errors and Solutions

Database Structure for Files

Main Tables

TSQL.APP stores file information in the following tables:

  1. api_files: The main table for file information

    • id: Unique identifier for the file
    • filename: Original file name
    • mimetype: MIME type of the file
    • filesize: Size in bytes
    • description: Optional description
    • context: Application context (usually the table name)
    • context_id: ID of the related record
    • file_category_id: Reference to category
    • created: Date/time of upload
    • created_by: User who uploaded the file
  2. api_file_category: Categories for files

    • id: Unique identifier for the category
    • name: Category name
    • description: Optional description

Relationships and Constraints

  • Each file in api_files is linked to a record in another table via context and context_id
  • Files can be categorized via the file_category_id foreign key
  • The physical files are stored in a file system, while the metadata is stored in the database

Important Query Examples

  1. Retrieve all files for a specific record:
SELECT f.id, f.filename, f.filesize, f.description, c.name AS category
FROM api_files f
LEFT JOIN api_file_category c ON f.file_category_id = c.id
WHERE f.context = 'your_table_name'
AND f.context_id = @record_id;
  1. Filter files by category:
SELECT f.id, f.filename, f.description
FROM api_files f
WHERE f.context = 'your_table_name'
AND f.context_id = @record_id
AND f.file_category_id = (SELECT id FROM api_file_category WHERE name = 'your_category');

File Functions and Stored Procedures

File Management Procedures

TSQL.APP provides various stored procedures for file management:

1. sp_sys_file_upload

Upload a file and attach it to a record.

Parameters:

  • @card_name: Name of the card/table
  • @id: ID of the record
  • @name: Name for the file (can be different from the original file name)
  • @user_name: User uploading the file
  • @mimetype: MIME type of the file
  • @modified: Modification date (optional)
  • @filesize: File size (optional)
  • @description: File description (optional)
  • @category: File category (optional)
  • @toast: Show confirmation message (optional)

Example:

EXEC sp_sys_file_upload 
    @card_name = N'customers',
    @id = 42,
    @name = N'Contract Document',
    @user_name = dbo.context_user(),
    @category = N'contracts';

2. sp_sys_file_preview

Open a file preview view.

Parameters:

  • @card_name: Name of the card/table
  • @id: ID of the record
  • @file_id: ID of the specific file (optional)
  • @print: Show print option (optional)
  • @height: Height of the preview (optional)

Example:

EXEC sp_sys_file_preview
    @card_name = N'customers',
    @id = 42,
    @file_id = 123,
    @print = 1;

3. sp_sys_file_delete

Delete a file.

Parameters:

  • @card_name: Name of the card/table
  • @id: ID of the record
  • @file_id: ID of the file to delete
  • @user_name: Username for tracking

Example:

EXEC sp_sys_file_delete
    @card_name = N'customers',
    @id = 42,
    @file_id = 123,
    @user_name = dbo.context_user();

Modal UI Components for Files

1. sp_api_modal_file

Simple file uploader for a single file.

Parameters:

  • @name: Name of the form control
  • @to_file_context: Context name (table)
  • @to_file_context_id: ID of the related record
  • @description: File description
  • @api_files_id: Output parameter for file ID
  • @url: Output parameter for file URL
  • @use_placeholder: Placeholder name (optional)
  • @category: File category (optional)
  • @resize_max: Maximum image size for resize (optional)
  • @resize_quality: Quality of resized images (optional)
  • @filename: Suggestion for file name (optional)

Example:

DECLARE @api_files_id INT;
DECLARE @url NVARCHAR(4000);

EXEC sp_api_modal_file
    @name = N'ProfilePhoto',
    @to_file_context = N'employees',
    @to_file_context_id = @id,
    @description = N'Employee profile photo',
    @api_files_id = @api_files_id OUT,
    @url = @url OUT,
    @category = N'photos';

2. sp_api_modal_file_multi

Advanced multi-file uploader with drag-and-drop interface.

Parameters:

  • @name: Name of the form control
  • @to_file_context: Context name (table)
  • @to_file_context_id: ID of the related record
  • @description: File description
  • @api_files_ids: Output parameter for file IDs (comma-separated)
  • @files_ready_for_use: Output parameter for readiness status
  • @category: File category (optional)
  • @message: Instruction message (optional)
  • @filesize_limit: Maximum file size (optional)
  • @upload_finished: Output parameter for completion status

Example:

DECLARE @api_files_ids NVARCHAR(MAX);
DECLARE @files_ready_for_use BIT;
DECLARE @upload_finished BIT;

EXEC sp_api_modal_file_multi
    @name = N'InvoiceAttachments',
    @to_file_context = N'invoices',
    @to_file_context_id = @id,
    @description = N'Invoice attachments',
    @api_files_ids = @api_files_ids OUT,
    @files_ready_for_use = @files_ready_for_use OUT,
    @category = N'financial',
    @message = N'Drop invoice files here or click to browse',
    @upload_finished = @upload_finished OUT;

File Uploads in Forms

Single File Upload Pattern

-- 1. Declare necessary variables
DECLARE @api_files_id INT;
DECLARE @url NVARCHAR(4000);
DECLARE @upload_button NVARCHAR(MAX);

-- 2. Synchronize with modal state
EXEC sp_api_modal_get_value @name='@upload_button', @value=@upload_button OUT;

-- 3. Add file uploader component
EXEC sp_api_modal_text @text=N'Upload Document', @class=N'font-weight-bold';
EXEC sp_api_modal_file
    @name = N'DocumentUpload',
    @to_file_context = N'customers',
    @to_file_context_id = @id,
    @description = N'Customer document',
    @api_files_id = @api_files_id OUT,
    @url = @url OUT,
    @category = N'documents';

-- 4. Process uploads
IF @api_files_id IS NOT NULL
BEGIN
    EXEC sp_api_toast @text=N'Document successfully uploaded', @class=N'btn-success';
END

Multi-File Upload Pattern

-- 1. Declare necessary variables
DECLARE @api_files_ids NVARCHAR(MAX);
DECLARE @files_ready_for_use BIT;
DECLARE @upload_finished BIT;

-- 2. Synchronize with modal state
EXEC sp_api_modal_get_value @name='@api_files_ids', @value=@api_files_ids OUT;
EXEC sp_api_modal_get_value @name='@files_ready_for_use', @value=@files_ready_for_use OUT;
EXEC sp_api_modal_get_value @name='@upload_finished', @value=@upload_finished OUT;

-- 3. Add multi-file uploader component
EXEC sp_api_modal_text @text=N'Upload Project Files', @class=N'font-weight-bold';
EXEC sp_api_modal_file_multi
    @name = N'ProjectFiles',
    @to_file_context = N'projects',
    @to_file_context_id = @id,
    @description = N'Project files and documents',
    @api_files_ids = @api_files_ids OUT,
    @files_ready_for_use = @files_ready_for_use OUT,
    @category = N'project_docs',
    @message = N'Drop project files here or click to browse',
    @upload_finished = @upload_finished OUT;

-- 4. Process uploads
IF @upload_finished = 1 AND @api_files_ids IS NOT NULL AND LEN(@api_files_ids) > 0
BEGIN
    EXEC sp_api_toast @text=N'Project files successfully uploaded', @class=N'btn-success';
END

Managing File Categories

File categories are a powerful way to organize uploads within your TSQL.APP application. They allow you to separate different types of files, apply filtering, and implement different processing.

Defining Categories

Categories are stored in the api_file_category table. They can be added via:

INSERT INTO api_file_category (name, description)
VALUES 
    (N'invoices', N'Invoice documents'),
    (N'contracts', N'Contract documents'),
    (N'photos', N'Photo attachments'),
    (N'technical', N'Technical specifications');

Filtering Files by Category

The correct way to filter files by category:

-- Retrieving files in a specific category
SELECT f.*
FROM api_files f
WHERE f.context = 'customers'
AND f.context_id = @customer_id
AND f.file_category_id = (SELECT id FROM api_file_category WHERE name = 'contracts');

Checking and Creating Categories

Pattern for checking if a category exists (and creating it if needed):

DECLARE @category_id INT;

-- Find the category ID
SELECT @category_id = id 
FROM api_file_category 
WHERE name = N'your_category';

-- Create the category if it doesn't exist
IF @category_id IS NULL
BEGIN
    INSERT INTO api_file_category (name, description)
    VALUES (N'your_category', N'Description of your category');
    
    SET @category_id = SCOPE_IDENTITY();
END

Practical Examples

Example 1: Invoice with Multi-Document Upload

-- Container form with file upload functionality
-- 1. Declare all variables at the beginning (TSQL.APP mandated practice)
DECLARE @invoice_number NVARCHAR(MAX);
DECLARE @invoice_date NVARCHAR(MAX);
DECLARE @amount DECIMAL(18,2);
DECLARE @description NVARCHAR(MAX);
DECLARE @input_button NVARCHAR(MAX);
DECLARE @Title NVARCHAR(MAX);
DECLARE @SubTitle NVARCHAR(MAX);
DECLARE @Message NVARCHAR(MAX);
DECLARE @api_files_ids NVARCHAR(MAX);
DECLARE @has_attachments BIT;
DECLARE @files_ready_for_use BIT;
DECLARE @upload_finished BIT;
DECLARE @file_description NVARCHAR(MAX);

-- 2. Synchronize with modal state
EXEC sp_api_modal_get_value @name='@invoice_number', @value=@invoice_number OUT;
EXEC sp_api_modal_get_value @name='@invoice_date', @value=@invoice_date OUT;
EXEC sp_api_modal_get_value @name='@amount', @value=@amount OUT;
EXEC sp_api_modal_get_value @name='@description', @value=@description OUT;
EXEC sp_api_modal_get_value @name='@input_button', @value=@input_button OUT;
EXEC sp_api_modal_get_value @name='@api_files_ids', @value=@api_files_ids OUT;
EXEC sp_api_modal_get_value @name='@files_ready_for_use', @value=@files_ready_for_use OUT;
EXEC sp_api_modal_get_value @name='@upload_finished', @value=@upload_finished OUT;

-- 3. Load existing data if available
IF @id > 0
BEGIN
    SELECT 
        @invoice_number = ISNULL(@invoice_number, invoice_number),
        @invoice_date = ISNULL(@invoice_date, CONVERT(NVARCHAR, invoice_date, 126)),
        @amount = ISNULL(@amount, amount),
        @description = ISNULL(@description, description)
    FROM invoices 
    WHERE id = @id;
END

-- 4. Check if there are existing attachments
SELECT @has_attachments = CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END
FROM api_files
WHERE context = 'invoices'
AND context_id = @id
AND file_category_id = (SELECT id FROM api_file_category WHERE name = 'invoice_docs');

-- 5. Build the form
SET @Title = N'Invoice Details';
SET @SubTitle = N'Enter invoice details and add attachments';
SET @file_description = N'Invoice attachments';

-- Title
EXEC sp_api_modal_text @text=@Title, @class=N'h3';
EXEC sp_api_modal_text @text=@SubTitle, @class=N'text-muted';

-- Invoice details section
EXEC sp_api_modal_text @text=N'Invoice Details', @class=N'h5';

-- Invoice number
EXEC sp_api_modal_text @text=N'Invoice Number:', @class=N'font-weight-bold';
EXEC sp_api_modal_input 
    @name = N'@invoice_number', 
    @value = @invoice_number OUT,
    @placeholder = N'Enter invoice number';

-- Invoice date
EXEC sp_api_modal_text @text=N'Invoice Date:', @class=N'font-weight-bold';
EXEC sp_api_modal_input_datetime 
    @name = N'@invoice_date', 
    @value = @invoice_date OUT;

-- Amount
EXEC sp_api_modal_text @text=N'Amount:', @class=N'font-weight-bold';
EXEC sp_api_modal_input_decimal 
    @name = N'@amount', 
    @value = @amount OUT,
    @precision = 18, 
    @scale = 2;

-- Description
EXEC sp_api_modal_text @text=N'Description:', @class=N'font-weight-bold';
EXEC sp_api_modal_input 
    @name = N'@description', 
    @value = @description OUT,
    @type = N'textarea',
    @placeholder = N'Enter description';

-- Attachment section
EXEC sp_api_modal_text @text=N'Invoice Attachments', @class=N'h5 mt-4';

-- Show status if needed
IF @has_attachments = 1
BEGIN
    EXEC sp_api_modal_text @text=N'There are attachments linked to this invoice', @class=N'text-success';
END

-- Multi-file uploader
EXEC sp_api_modal_file_multi
    @name = N'InvoiceFiles',
    @to_file_context = N'invoices',
    @to_file_context_id = @id,
    @description = @file_description,
    @api_files_ids = @api_files_ids OUT,
    @files_ready_for_use = @files_ready_for_use OUT,
    @category = N'invoice_docs',
    @message = N'Drop invoice attachments here or click to browse',
    @upload_finished = @upload_finished OUT;

-- Show upload status if needed
IF @upload_finished = 1 AND @api_files_ids IS NOT NULL AND LEN(@api_files_ids) > 0
BEGIN
    SET @Message = N'Attachments successfully uploaded.';
    EXEC sp_api_modal_text @text=@Message, @class=N'text-success';
END

-- Horizontal line
EXEC sp_api_modal_text @text=N'<hr>', @class=N'mt-4 mb-4';

-- Save button
EXEC sp_api_modal_button 
    @name = N'@input_button',
    @value = N'Save Invoice',
    @valueout = @input_button OUT,
    @class = N'btn-success',
    @key = N'Enter';

-- 6. Process form submit
IF @input_button IS NOT NULL
BEGIN
    -- Validation
    IF @invoice_number IS NULL OR LEN(TRIM(@invoice_number)) = 0
    BEGIN
        SET @Message = N'Please enter a valid invoice number.';
        EXEC sp_api_toast @text=@Message, @class=N'btn-warning';
        RETURN;
    END
    
    IF @amount IS NULL OR @amount <= 0
    BEGIN
        SET @Message = N'Please enter a valid amount.';
        EXEC sp_api_toast @text=@Message, @class=N'btn-warning';
        RETURN;
    END
    
    -- Update or insert record
    IF @id > 0
    BEGIN
        -- Update existing invoice
        UPDATE invoices 
        SET invoice_number = @invoice_number,
            invoice_date = CONVERT(DATE, @invoice_date),
            amount = @amount,
            description = @description,
            last_updated = GETDATE()
        WHERE id = @id;
    END
    ELSE
    BEGIN
        -- Add new invoice
        INSERT INTO invoices (
            invoice_number, 
            invoice_date, 
            amount, 
            description, 
            created_date,
            last_updated
        )
        VALUES (
            @invoice_number,
            CONVERT(DATE, @invoice_date),
            @amount,
            @description,
            GETDATE(),
            GETDATE()
        );
        
        -- Get new ID for file context 
        SET @id = SCOPE_IDENTITY();
        
        -- Update file context with new ID if files were uploaded
        IF @api_files_ids IS NOT NULL AND LEN(@api_files_ids) > 0
        BEGIN
            UPDATE api_files
            SET context_id = @id
            WHERE id IN (SELECT value FROM STRING_SPLIT(@api_files_ids, ','))
            AND context = 'invoices'
            AND context_id IS NULL;
        END
    END
    
    -- Show confirmation and close modal
    SET @Message = N'Invoice successfully saved!';
    EXEC sp_api_toast @text=@Message, @class=N'btn-success';
    EXEC sp_api_modal_clear;
    RETURN;
END

Example 2: Document Preview and Management

-- Document preview and management form
DECLARE @doc_title NVARCHAR(MAX);
DECLARE @doc_type NVARCHAR(MAX);
DECLARE @view_button NVARCHAR(MAX);
DECLARE @print_button NVARCHAR(MAX);
DECLARE @delete_button NVARCHAR(MAX);
DECLARE @back_button NVARCHAR(MAX);
DECLARE @Title NVARCHAR(MAX);
DECLARE @Message NVARCHAR(MAX);
DECLARE @file_id INT;
DECLARE @has_file BIT;
DECLARE @filename NVARCHAR(MAX);

-- Synchronize with modal state
EXEC sp_api_modal_get_value @name='@doc_title', @value=@doc_title OUT;
EXEC sp_api_modal_get_value @name='@doc_type', @value=@doc_type OUT;
EXEC sp_api_modal_get_value @name='@view_button', @value=@view_button OUT;
EXEC sp_api_modal_get_value @name='@print_button', @value=@print_button OUT;
EXEC sp_api_modal_get_value @name='@delete_button', @value=@delete_button OUT;
EXEC sp_api_modal_get_value @name='@back_button', @value=@back_button OUT;
EXEC sp_api_modal_get_value @name='@file_id', @value=@file_id OUT;

-- Retrieve document data
SELECT @doc_title = title,
       @doc_type = document_type
FROM documents
WHERE id = @id;

-- Retrieve file data
SELECT TOP 1 
    @file_id = f.id,
    @filename = f.filename,
    @has_file = 1
FROM api_files f
WHERE f.context = 'documents'
AND f.context_id = @id
ORDER BY f.id DESC;

-- Build the form
SET @Title = N'Document Details';

-- Title
EXEC sp_api_modal_text @text=@Title, @class=N'h3';

-- Document information
EXEC sp_api_modal_text @text=N'Document Information', @class=N'h5';

-- Title
EXEC sp_api_modal_text @text=N'Title:', @class=N'font-weight-bold';
EXEC sp_api_modal_input 
    @name = N'@doc_title', 
    @value = @doc_title OUT,
    @placeholder = N'Document title';

-- Type
EXEC sp_api_modal_text @text=N'Document Type:', @class=N'font-weight-bold';
EXEC sp_api_modal_input 
    @name = N'@doc_type', 
    @value = @doc_type OUT,
    @placeholder = N'Document type';

-- File information section
EXEC sp_api_modal_text @text=N'File Information', @class=N'h5 mt-4';

IF @has_file = 1
BEGIN
    -- Show file information
    SET @Message = CONCAT(N'Current file: ', @filename);
    EXEC sp_api_modal_text @text=@Message, @class=N'text-info';
    
    -- Buttons section
    EXEC sp_api_modal_text @text=N'File Actions', @class=N'h6 mt-3';
    
    -- View button
    EXEC sp_api_modal_button 
        @name = N'@view_button',
        @value = N'View Document',
        @valueout = @view_button OUT,
        @class = N'btn-primary',
        @inline = 1;
        
    -- Print button
    EXEC sp_api_modal_button 
        @name = N'@print_button',
        @value = N'Print Document',
        @valueout = @print_button OUT,
        @class = N'btn-info',
        @inline = 1;
        
    -- Delete button
    EXEC sp_api_modal_button 
        @name = N'@delete_button',
        @value = N'Delete Document',
        @valueout = @delete_button OUT,
        @class = N'btn-danger',
        @inline = 1;
END
ELSE
BEGIN
    -- No file found message
    EXEC sp_api_modal_text @text=N'No file linked to this document.', @class=N'text-warning';
    
    -- Upload section
    EXEC sp_api_modal_text @text=N'Upload Document', @class=N'h6 mt-3';
    
    -- File uploader
    DECLARE @api_files_id INT;
    DECLARE @url NVARCHAR(4000);
    
    EXEC sp_api_modal_file
        @name = N'DocumentFile',
        @to_file_context = N'documents',
        @to_file_context_id = @id,
        @description = @doc_title,
        @api_files_id = @api_files_id OUT,
        @url = @url OUT,
        @category = N'document';
        
    -- Show message if a file is uploaded
    IF @api_files_id IS NOT NULL
    BEGIN
        SET @Message = N'Document successfully uploaded!';
        EXEC sp_api_toast @text=@Message, @class=N'btn-success';
        
        -- Refresh the page to show the new file
        EXEC sp_api_modal_restart;
        RETURN;
    END
END

-- Horizontal line
EXEC sp_api_modal_text @text=N'<hr>', @class=N'mt-4 mb-4';

-- Back button
EXEC sp_api_modal_button 
    @name = N'@back_button',
    @value = N'Back to List',
    @valueout = @back_button OUT,
    @class = N'btn-secondary';

-- Process button actions
IF @view_button IS NOT NULL
BEGIN
    -- Open document preview
    EXEC sp_sys_file_preview
        @card_name = N'documents',
        @id = @id,
        @file_id = @file_id;
    
    RETURN;
END

IF @print_button IS NOT NULL
BEGIN
    -- Open document preview with print option
    EXEC sp_sys_file_preview
        @card_name = N'documents',
        @id = @id,
        @file_id = @file_id,
        @print = 1;
    
    RETURN;
END

IF @delete_button IS NOT NULL
BEGIN
    -- Delete file
    EXEC sp_sys_file_delete
        @card_name = N'documents',
        @id = @id,
        @file_id = @file_id,
        @user_name = dbo.context_user();
    
    SET @Message = N'Document successfully deleted!';
    EXEC sp_api_toast @text=@Message, @class=N'btn-success';
    
    -- Refresh the page to show the updated status
    EXEC sp_api_modal_restart;
    RETURN;
END

IF @back_button IS NOT NULL
BEGIN
    -- Go back to the document list
    EXEC sp_api_modal_clear;
    RETURN;
END

Common Errors and Solutions

1. Incorrect Category Filtering

Error:

-- INCORRECT: Direct reference to category name
SELECT * FROM api_files
WHERE context = 'customers'
AND context_id = @id
AND category = 'photos';  -- This column doesn't exist

Solution:

-- CORRECT: Use file_category_id with subquery
SELECT * FROM api_files
WHERE context = 'customers'
AND context_id = @id
AND file_category_id = (SELECT id FROM api_file_category WHERE name = 'photos');

2. Missing OUT Parameters

Error:

-- INCORRECT: Missing OUT parameters in sp_api_modal_file_multi
EXEC sp_api_modal_file_multi
    @name = N'DocFiles',
    @to_file_context = N'documents',
    @to_file_context_id = @id,
    @category = N'document';  -- Missing required OUT parameters

Solution:

-- CORRECT: All required OUT parameters
DECLARE @api_files_ids NVARCHAR(MAX);
DECLARE @files_ready_for_use BIT;
DECLARE @upload_finished BIT;

EXEC sp_api_modal_file_multi
    @name = N'DocFiles',
    @to_file_context = N'documents',
    @to_file_context_id = @id,
    @description = N'Document files',
    @api_files_ids = @api_files_ids OUT,
    @files_ready_for_use = @files_ready_for_use OUT,
    @category = N'document',
    @upload_finished = @upload_finished OUT;

3. Apostrophes in String Parameters

Error:

-- INCORRECT: Apostrophe in string literal
SET @message = N'Let's upload files';  -- This causes a syntax error

Solution:

-- CORRECT: Either double the apostrophes or avoid them
SET @message = N'Lets upload files';
-- Or
SET @message = N'Let''s upload files';

4. Missing Initialization of Upload Variables

Error:

-- INCORRECT: Using variables without initialization
IF @upload_finished = 1 AND @api_files_ids IS NOT NULL
BEGIN
    -- Processing code
END

Solution:

-- CORRECT: Declare and synchronize all variables
DECLARE @api_files_ids NVARCHAR(MAX);
DECLARE @upload_finished BIT;

EXEC sp_api_modal_get_value @name='@api_files_ids', @value=@api_files_ids OUT;
EXEC sp_api_modal_get_value @name='@upload_finished', @value=@upload_finished OUT;

IF @upload_finished = 1 AND @api_files_ids IS NOT NULL
BEGIN
    -- Processing code
END

5. Improper Context ID Handling for New Records

Error:

-- INCORRECT: Using @to_file_context_id = @id when @id is not set
EXEC sp_api_modal_file_multi
    @name = N'Attachments',
    @to_file_context = N'customers',
    @to_file_context_id = @id,  -- @id might be NULL for new records
    @description = N'Customer attachments',
    @api_files_ids = @api_files_ids OUT,
    @files_ready_for_use = @files_ready_for_use OUT,
    @category = N'attachments',
    @upload_finished = @upload_finished OUT;

Solution:

-- CORRECT: Update context_id after insert for new records
IF @id IS NULL OR @id = 0
BEGIN
    -- Insert the main record first
    INSERT INTO customers (name, email) VALUES (@name, @email);
    SET @id = SCOPE_IDENTITY();
    
    -- Then update any uploaded files with the new ID
    IF @api_files_ids IS NOT NULL AND LEN(@api_files_ids) > 0
    BEGIN
        UPDATE api_files
        SET context_id = @id
        WHERE id IN (SELECT value FROM STRING_SPLIT(@api_files_ids, ','))
        AND context = 'customers'
        AND context_id IS NULL;
    END
END

By following these best practices and examples, you can effectively implement file management functionality in your TSQL.APP applications while avoiding common pitfalls and errors.