UnitOfWork Examples

Basic CRUD

using var uow = new UnitofWork<Customer>(editor, "MyDB", "Customers", "Id");

// Create
uow.New();
uow.CurrentItem.Name = "John Doe";
uow.CurrentItem.Email = "john@example.com";

// Read
var all = await uow.Get();
var customer = uow.Get("123");

// Update
customer.Name = "Jane Doe";
uow.Update(customer);

// Delete
uow.Delete(customer);

// Commit
var result = await uow.Commit();
if (result.Flag != Errors.Ok)
    Console.WriteLine(result.Message);

Undo/Redo

uow.IsUndoEnabled = true;
uow.MaxUndoDepth = 50;

// Make changes
customer.Name = "Changed";

// Undo
uow.Undo(); // Name reverts to original

// Redo
uow.Redo(); // Name goes back to "Changed"

Validation

uow.IsAutoValidateEnabled = true;
uow.BlockCommitOnValidationError = true;

var result = uow.ValidateAll();
if (!result.IsValid)
{
    foreach (var error in result.Errors)
        Console.WriteLine($"{error.PropertyName}: {error.Message}");
}

DataView Examples

Create Federated View

var viewConnection = new DataViewConnection(editor);
viewConnection.AddConnection("CustomersDB", customerDs);
viewConnection.AddConnection("OrdersDB", ordersDs);

var viewDs = new DataViewDataSource("CustomerOrders", viewConnection, editor);

// Define entities
viewDs.AddEntity(new EntityStructure
{
    EntityName = "CustomerView",
    DataSourceID = "CustomersDB",
    EntityID = "Customers"
});

viewDs.AddEntity(new EntityStructure
{
    EntityName = "OrderView",
    DataSourceID = "OrdersDB",
    EntityID = "Orders"
});

// Define join
var joinGraph = new JoinGraph();
joinGraph.AddJoin(new EntityJoin
{
    LeftEntity = "CustomerView",
    RightEntity = "OrderView",
    LeftField = "CustomerId",
    RightField = "CustomerId",
    JoinType = JoinType.Left
});

viewDs.SetJoinGraph(joinGraph);

// Query
var results = viewDs.GetEntity("CustomerView", new List<AppFilter>());

Caching Examples

Initialize Cache

// Simple in-memory cache
CacheManager.Initialize();

// Redis with fallback
CacheManager.Initialize(
    new CacheConfiguration
    {
        DefaultExpiry = TimeSpan.FromMinutes(30),
        MaxItems = 10000,
        Redis = new RedisConfiguration
        {
            ConnectionString = "localhost:6379"
        }
    },
    primaryProvider: CacheProviderType.Redis,
    fallbackProvider: CacheProviderType.InMemory);

// Store data
await CacheManager.SetAsync("user:123", userData, TimeSpan.FromMinutes(30));

// Retrieve
var user = await CacheManager.GetAsync<UserData>("user:123");

// GetOrCreate
var data = await CacheManager.GetOrCreateAsync("expensive:key", async () =>
{
    return await ComputeExpensiveOperation();
}, TimeSpan.FromHours(1));

Tagged Caching

// Tag items
await CacheManager.SetWithTagsAsync("item:1", data,
    new[] { "user", "recent" });

// Invalidate by tag
await CacheManager.RemoveByTagAsync("user");

Proxy DataSource Examples

Basic Failover

var proxy = new ProxyDataSource(editor,
    new List<string> { "PrimaryDB", "Replica1", "Replica2" });

// Query (automatically routes to healthy target)
var data = proxy.GetEntity("Customers", new List<AppFilter>());

// Failover event
proxy.OnFailover += (s, e) =>
    Console.WriteLine($"Failover: {e.FromDataSource} -> {e.ToDataSource}");

Circuit Breaker

proxy.SetFailureThreshold(5);
proxy.SetCircuitResetTimeout(TimeSpan.FromMinutes(5));

// Check metrics
var metrics = proxy.GetMetrics();
Console.WriteLine($"Success rate: {metrics.SuccessRate:F1}%");
Console.WriteLine($"Avg latency: {metrics.AverageResponseTime}ms");

Rules Engine Examples

Define and Execute Rules

var engine = new RulesEngine(editor);

// Register rules
engine.RegisterRule("ValidateAge", "Age >= 18 AND Age <= 120");
engine.RegisterRule("ComputeDiscount", "Price * (1 - DiscountRate)");

// Execute
var result = engine.Execute("ValidateAge", new { Age = 25 });
if (result.Success)
    Console.WriteLine("Age is valid");

// Execute with context
var context = new RuleContext
{
    Data = customer,
    Parameters = new Dictionary<string, object>
    {
        ["MaxDiscount"] = 0.20
    }
};
var discount = engine.Execute("ComputeDiscount", context);

Built-in Rules

// Data quality
var dqRule = new IsNotNullRule { FieldName = "Email" };
var result = dqRule.Execute(customer);

// Date operations
var dateRule = new DateDiffRule
{
    FieldName = "BirthDate",
    TargetDate = DateTime.Now,
    OutputField = "Age"
};

// Transform
var transformRule = new StringReplaceRule
{
    FieldName = "Phone",
    Pattern = "-",
    Replacement = ""
};

Service Registration Examples

Corrected (2026). These samples previously used AddBeepForDesktop / AddBeepForWeb / AddBeepForBlazorServer and app.UseBeepForWeb(). None of those methods exist — nor do the MaxConnectionPoolSize and EnableSignalRSupport options they set. The real entry point is AddBeepServices(); pick the lifetime with AsSingleton() or AsScoped().

Desktop Application

var builder = Host.CreateApplicationBuilder();

IBeepService beepService = builder.Services.AddBeepServices()
    .WithDirectory(AppContext.BaseDirectory)
    .WithAppRepo("MyDesktopApp")
    .WithConfigType(BeepConfigType.Application)
    .WithAssemblyLoading()
    .WithMapping()
    .AsSingleton()          // singleton for desktop
    .Build();

var host = builder.Build();

// Load plugins with progress reporting
var progress = new Progress<PassedArgs>(args =>
    Console.WriteLine($"Loading: {args.Messege}"));
beepService.LoadAssemblies(progress);

Build() returns the IBeepService directly, so you do not need to resolve it from the provider afterwards. Note PassedArgs.Messege is spelled that way in the contract.

Web API

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddBeepServices()
    .WithDirectory(Path.Combine(AppContext.BaseDirectory, "Beep"))
    .WithAppRepo("MyWebApi")
    .WithConfigType(BeepConfigType.Application)
    .AsScoped()             // scoped for web
    .Build();

var app = builder.Build();
// No UseBeepForWeb() middleware exists - nothing further to wire up.

Blazor Server

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddBeepServices()
    .WithDirectory(AppContext.BaseDirectory)
    .WithAppRepo("MyBlazorApp")
    .WithConfigType(BeepConfigType.Application)
    .AsScoped()             // scoped for Blazor Server
    .Build();

builder.Services.AddRazorComponents()
    .AddInteractiveServerComponents();

With a scoped registration the components are resolved by key — e.g. [Inject] IDMEEditor Editor requires GetRequiredKeyedService<IDMEEditor>("Editor") semantics. See BeepService → DI Service Registration for why the singleton and scoped paths differ.

Migration Examples

Basic Migration

var migrationManager = new MigrationManager(editor);

// Create migration
var migration = new Migration
{
    Name = "Add Customer Table",
    Version = "1.0.0",
    Up = async () =>
    {
        var ds = editor.GetDataSource("MyDB");
        await ds.ExecuteSql(@"
            CREATE TABLE Customers (
                Id INTEGER PRIMARY KEY,
                Name TEXT NOT NULL,
                Email TEXT
            )");
    },
    Down = async () =>
    {
        var ds = editor.GetDataSource("MyDB");
        await ds.ExecuteSql("DROP TABLE Customers");
    }
};

// Apply
await migrationManager.ApplyAsync(migration);

Migration with Validation

// Validate before applying
var validation = await migrationManager.ValidateAsync(migration);
if (!validation.IsValid)
{
    foreach (var error in validation.Errors)
        Console.WriteLine(error);
    return;
}

// Apply with rollback on failure
await migrationManager.ApplyWithRollbackAsync(migration);