Victor A

29 min read

.NET Azure Developer Interview Study Guide - Complete Questions & Answers

Technical.NETAzureDevelopment

.NET Azure Developer Interview Study Guide

Complete Questions & Answers with Practical Examples

<div class="intro-section">
  <p>This comprehensive study guide provides detailed answers to common .NET Azure developer interview questions. Each answer includes practical examples, code snippets, and the depth of knowledge expected in technical interviews.</p>
</div>

<div class="part-header">Part 1: Core .NET & C# Technical Questions</div>

<div class="question-block">
  <h3 class="question-title">Q1: Explain the difference between IEnumerable and IQueryable</h3>
  <span class="answer-label">Expected Answer</span>

  <p class="content-text"><strong>IEnumerable:</strong></p>
  <ul class="content-list">
    <li>Represents a forward-only cursor of data in memory</li>
    <li>Best for in-memory collections (List, Array, etc.)</li>
    <li>LINQ operations are executed in memory using LINQ to Objects</li>
    <li>All data is loaded into memory before filtering</li>
    <li>Returns data as-is from the data source</li>
  </ul>

  <p class="content-text"><strong>IQueryable:</strong></p>
  <ul class="content-list">
    <li>Represents a query that hasn't been executed yet</li>
    <li>Best for remote data sources (databases, web services)</li>
    <li>LINQ operations are translated to the source query language (SQL for databases)</li>
    <li>Filters are applied at the data source before loading into memory</li>
    <li>Supports lazy loading and query optimization</li>
  </ul>

  <p class="practical-example-header">Practical Example:</p>
  <div class="code-example">
    <pre><code>// IEnumerable - loads ALL products into memory first, then filters

IEnumerable<Product> products = dbContext.Products.ToList(); var expensiveProducts = products.Where(p => p.Price > 100); // Filters in memory

// IQueryable - builds SQL query, only loads filtered results IQueryable<Product> productsQuery = dbContext.Products; var expensiveProducts = productsQuery.Where(p => p.Price > 100); // Translates to SQL WHERE clause

// The SQL generated for IQueryable would be: // SELECT * FROM Products WHERE Price > 100

// Performance difference: // If you have 1 million products but only 10 are > $100: // - IEnumerable loads 1 million records, then filters to 10 // - IQueryable loads only 10 records from the database

  <div class="when-to-use">
    <p><strong>When to use each:</strong></p>
    <p>Use <strong>IEnumerable</strong> when working with small in-memory collections or when you need to apply complex logic that can't be translated to SQL</p>
    <p>Use <strong>IQueryable</strong> when working with databases to optimize performance by filtering at the source</p>
  </div>
</div>

<div class="question-block">
  <h3 class="question-title">Q2: How does Garbage Collection work in .NET?</h3>
  <span class="answer-label">Expected Answer</span>

  <p class="content-text">.NET uses an automatic memory management system with a generational garbage collector. Here's how it works:</p>

  <p class="content-text"><strong>Generational Collection:</strong></p>
  <ul class="content-list">
    <li><strong>Generation 0:</strong> Newly allocated objects (short-lived)</li>
    <li><strong>Generation 1:</strong> Objects that survived one GC (medium-lived)</li>
    <li><strong>Generation 2:</strong> Objects that survived multiple GCs (long-lived)</li>
  </ul>

  <p class="content-text"><strong>The GC Process:</strong></p>
  <ul class="content-list">
    <li><strong>Allocation:</strong> New objects go to Gen 0</li>
    <li><strong>Collection Trigger:</strong> When Gen 0 fills up, GC runs</li>
    <li><strong>Mark Phase:</strong> GC identifies reachable objects starting from roots (stack variables, static fields, etc.)</li>
    <li><strong>Sweep Phase:</strong> Unreferenced objects are marked for collection</li>
    <li><strong>Compact Phase:</strong> Memory is compacted, survivors promoted to next generation</li>
  </ul>

  <p class="practical-example-header">Code Example:</p>
  <div class="code-example">
    <pre><code>public class GarbageCollectionExample

{ public void DemonstrateGC() { // Objects created here are in Generation 0 var shortLived = new byte[1000];

    // Force garbage collection (don't do this in production!)
    GC.Collect(0); // Collect Generation 0

    // If shortLived survives, it moves to Generation 1
    var longLived = new byte[1000000];

    // Check object generation
    Console.WriteLine($"Generation: {GC.GetGeneration(longLived)}");

    // Large objects (>85KB) go directly to Large Object Heap (LOH)
    var largeObject = new byte[90000];
    // LOH is collected with Generation 2
}

// Best practices for GC optimization
public void OptimizeForGC()
{
    // 1. Use object pooling for frequently created objects
    var stringBuilder = StringBuilderPool.Rent();
    try
    {
        // Use the string builder
    }
    finally
    {
        StringBuilderPool.Return(stringBuilder);
    }

    // 2. Implement IDisposable for unmanaged resources
    using (var stream = new FileStream("file.txt", FileMode.Open))
    {
        // Stream is disposed automatically
    }

    // 3. Avoid finalizers unless necessary
    // 4. Use ValueTypes (struct) for small, immutable data
    // 5. Minimize allocations in hot paths
}

}

  <div class="key-concepts">
    <h4>Key Points to Remember:</h4>
    <ul>
      <li>GC is non-deterministic (you can't predict exactly when it runs)</li>
      <li>Finalizers delay garbage collection (objects go through additional cycle)</li>
      <li>Use <code>IDisposable</code> pattern for deterministic cleanup</li>
      <li>Large Object Heap (LOH) fragmentation can be an issue in long-running applications</li>
    </ul>
  </div>
</div>

<div class="question-block">
  <h3 class="question-title">Q3: What are the different types of caching available in Azure?</h3>
  <span class="answer-label">Expected Answer</span>

  <p class="content-text">Azure offers multiple caching solutions for different scenarios:</p>

  <p class="content-text"><strong>1. Azure Cache for Redis</strong></p>
  <ul class="content-list">
    <li>In-memory data store based on Redis</li>
    <li>Supports complex data structures (strings, hashes, lists, sets)</li>
    <li>Use cases: Session state, output caching, distributed caching</li>
  </ul>

  <div class="code-example">
    <pre><code>public class RedisCacheService

{ private readonly IConnectionMultiplexer _redis; private readonly IDatabase _cache;

public RedisCacheService(string connectionString)
{
    _redis = ConnectionMultiplexer.Connect(connectionString);
    _cache = _redis.GetDatabase();
}

public async Task&lt;T&gt; GetAsync&lt;T&gt;(string key, Func&lt;Task&lt;T&gt;&gt; factory, TimeSpan expiration)
{
    var cached = await _cache.StringGetAsync(key);
    if (cached.HasValue)
    {
        return JsonSerializer.Deserialize&lt;T&gt;(cached);
    }

    var value = await factory();
    await _cache.StringSetAsync(key, JsonSerializer.Serialize(value), expiration);
    return value;
}

}

  <p class="content-text"><strong>2. In-Memory Caching (IMemoryCache)</strong></p>
  <ul class="content-list">
    <li>Local to application instance</li>
    <li>Fastest option but not distributed</li>
    <li>Lost on application restart</li>
  </ul>

  <div class="code-example">
    <pre><code>public class InMemoryCacheService

{ private readonly IMemoryCache _cache;

public async Task&lt;T&gt; GetOrCreateAsync&lt;T&gt;(string key, Func&lt;Task&lt;T&gt;&gt; factory)
{
    return await _cache.GetOrCreateAsync(key, async entry =>
    {
        entry.SlidingExpiration = TimeSpan.FromMinutes(5);
        entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1);
        return await factory();
    });
}

}

  <p class="content-text"><strong>3. Azure CDN (Content Delivery Network)</strong></p>
  <ul class="content-list">
    <li>Edge caching for static content</li>
    <li>Geographic distribution</li>
    <li>Reduces latency for global users</li>
  </ul>

  <p class="content-text"><strong>4. Azure Front Door Caching</strong></p>
  <ul class="content-list">
    <li>Caches at edge locations</li>
    <li>URL-based caching rules</li>
    <li>Good for dynamic content with predictable patterns</li>
  </ul>

  <p class="content-text"><strong>5. Application-Level Response Caching</strong></p>
  <div class="code-example">
    <pre><code>[ApiController]

public class ProductController : ControllerBase { [HttpGet] [ResponseCache(Duration = 300, VaryByQueryKeys = new[] { "category" })] public async Task<IActionResult> GetProducts([FromQuery] string category) { // Response cached for 5 minutes per category return Ok(await _productService.GetProductsAsync(category)); } }

  <p class="practical-example-header">Caching Strategy Decision Matrix:</p>
  <table class="comparison-table">
    <thead>
      <tr>
        <th>Cache Type</th>
        <th>Use When</th>
        <th>Pros</th>
        <th>Cons</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>In-Memory</td>
        <td>Single instance, small data</td>
        <td>Fastest</td>
        <td>Not distributed</td>
      </tr>
      <tr>
        <td>Redis</td>
        <td>Distributed, complex data</td>
        <td>Scalable, persistent</td>
        <td>Network latency</td>
      </tr>
      <tr>
        <td>CDN</td>
        <td>Static files, global users</td>
        <td>Edge locations</td>
        <td>Static content only</td>
      </tr>
      <tr>
        <td>Front Door</td>
        <td>Dynamic content, global</td>
        <td>Smart routing</td>
        <td>More complex setup</td>
      </tr>
    </tbody>
  </table>
</div>

<div class="question-block">
  <h3 class="question-title">Q4: How do you handle distributed transactions in microservices?</h3>
  <span class="answer-label">Expected Answer</span>

  <p class="content-text">Distributed transactions in microservices are challenging because traditional ACID transactions don't work across service boundaries. Here are the main patterns:</p>

  <p class="content-text"><strong>1. Saga Pattern</strong></p>
  <p class="content-text">Series of local transactions coordinated through events. Two types: Choreography and Orchestration</p>

  <p class="practical-example-header">Orchestration Example:</p>
  <div class="code-example">
    <pre><code>public class OrderSaga

{ private readonly IServiceBus _serviceBus;

public async Task&lt;bool&gt; ProcessOrderAsync(Order order)
{
    var sagaId = Guid.NewGuid();
    var compensations = new Stack&lt;Func&lt;Task&gt;&gt;();

    try
    {
        // Step 1: Reserve Inventory
        var inventoryReserved = await _inventoryService.ReserveItemsAsync(order.Items, sagaId);
        compensations.Push(async () => await _inventoryService.ReleaseReservationAsync(sagaId));

        // Step 2: Process Payment
        var paymentProcessed = await _paymentService.ChargeAsync(order.PaymentInfo, sagaId);
        compensations.Push(async () => await _paymentService.RefundAsync(sagaId));

        // Step 3: Create Shipment
        var shipmentCreated = await _shippingService.CreateShipmentAsync(order, sagaId);
        compensations.Push(async () => await _shippingService.CancelShipmentAsync(sagaId));

        // All successful - confirm the transaction
        await ConfirmSagaAsync(sagaId);
        return true;
    }
    catch (Exception ex)
    {
        // Compensate in reverse order
        while (compensations.Count > 0)
        {
            var compensation = compensations.Pop();
            await compensation();
        }

        await _logger.LogSagaFailureAsync(sagaId, ex);
        return false;
    }
}

}

  <p class="content-text"><strong>2. Event Sourcing with CQRS</strong></p>
  <div class="code-example">
    <pre><code>public class OrderAggregate

{ private readonly List<IEvent> _events = new();

public void PlaceOrder(OrderDetails details)
{
    // Business logic validation
    if (!IsValid(details))
        throw new InvalidOrderException();

    // Raise domain event
    RaiseEvent(new OrderPlacedEvent
    {
        OrderId = Guid.NewGuid(),
        CustomerId = details.CustomerId,
        Items = details.Items,
        Timestamp = DateTime.UtcNow
    });
}

private void RaiseEvent(IEvent @event)
{
    _events.Add(@event);
    Apply(@event);
}

private void Apply(IEvent @event)
{
    // Update aggregate state based on event
    switch (@event)
    {
        case OrderPlacedEvent e:
            OrderId = e.OrderId;
            Status = OrderStatus.Placed;
            break;
    }
}

}

  <p class="content-text"><strong>3. Outbox Pattern</strong></p>
  <div class="code-example">
    <pre><code>public class OutboxPattern

{ public async Task SaveOrderWithEventsAsync(Order order) { using var transaction = await _dbContext.Database.BeginTransactionAsync();

    try
    {
        // Save business data
        _dbContext.Orders.Add(order);

        // Save events to outbox table in same transaction
        var outboxEvent = new OutboxEvent
        {
            Id = Guid.NewGuid(),
            EventType = "OrderCreated",
            Payload = JsonSerializer.Serialize(order),
            CreatedAt = DateTime.UtcNow,
            Processed = false
        };
        _dbContext.OutboxEvents.Add(outboxEvent);

        await _dbContext.SaveChangesAsync();
        await transaction.CommitAsync();
    }
    catch
    {
        await transaction.RollbackAsync();
        throw;
    }
}

// Background service publishes events
public async Task ProcessOutboxEventsAsync()
{
    var unpublishedEvents = await _dbContext.OutboxEvents
        .Where(e => !e.Processed)
        .OrderBy(e => e.CreatedAt)
        .ToListAsync();

    foreach (var @event in unpublishedEvents)
    {
        await _messageBus.PublishAsync(@event.EventType, @event.Payload);
        @event.Processed = true;
        @event.ProcessedAt = DateTime.UtcNow;
    }

    await _dbContext.SaveChangesAsync();
}

}

  <div class="best-practices">
    <h4>Best Practices:</h4>
    <ol>
      <li>Accept eventual consistency</li>
      <li>Design idempotent operations</li>
      <li>Implement correlation IDs for tracking</li>
      <li>Use compensating transactions for rollbacks</li>
      <li>Consider using Azure Service Bus or Event Grid for messaging</li>
    </ol>
  </div>
</div>

<div class="question-block">
  <h3 class="question-title">Q5: Explain the authentication flow using Azure AD in a web application</h3>
  <span class="answer-label">Expected Answer</span>

  <p class="content-text"><strong>OAuth 2.0 / OpenID Connect Flow with Azure AD:</strong></p>

  <p class="practical-example-header">1. Configuration in Startup.cs:</p>
  <div class="code-example">
    <pre><code>public class Startup

{ public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"));

    services.AddAuthorization(options =>
    {
        options.AddPolicy("RequireAdminRole",
            policy => policy.RequireRole("Admin"));

        options.AddPolicy("RequireEmployeeScope",
            policy => policy.RequireClaim("scope", "employee.read"));
    });

    services.AddMicrosoftIdentityWebApiAuthentication(Configuration, "AzureAd");
}

}

  <p class="practical-example-header">2. Authentication Flow Steps:</p>
  <div class="code-example">
    <pre><code>public class AuthenticationFlow

{ // Step 1: User attempts to access protected resource [Authorize] public class SecureController : Controller { public IActionResult Index() { // User is redirected to Azure AD login if not authenticated return View(); } }

// Step 2: After Azure AD authentication, tokens are received
public class TokenService
{
    private readonly ITokenAcquisition _tokenAcquisition;

    public async Task&lt;string&gt; GetAccessTokenAsync()
    {
        // Get token for calling downstream API
        var scopes = new[] { "api://your-api/.default" };
        var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(scopes);

        // Token structure:
        // Header.Payload.Signature (JWT)
        // Payload contains: sub (user), aud (audience), exp (expiry), roles, etc.

        return accessToken;
    }
}

// Step 3: Use token to call protected APIs
public class ApiClient
{
    private readonly HttpClient _httpClient;
    private readonly ITokenAcquisition _tokenAcquisition;

    public async Task&lt;T&gt; CallProtectedApiAsync&lt;T&gt;(string endpoint)
    {
        var token = await _tokenAcquisition.GetAccessTokenForUserAsync(new[] { "api.scope" });

        _httpClient.DefaultRequestHeaders.Authorization =
            new AuthenticationHeaderValue("Bearer", token);

        var response = await _httpClient.GetAsync(endpoint);
        response.EnsureSuccessStatusCode();

        return await response.Content.ReadFromJsonAsync&lt;T&gt;();
    }
}

}

  <p class="practical-example-header">3. Token Validation in API:</p>
  <div class="code-example">
    <pre><code>[ApiController]

[Authorize] public class ProtectedApiController : ControllerBase { [HttpGet] [RequiredScope("read:data")] public async Task<IActionResult> GetData() { // Azure AD validates: // 1. Token signature // 2. Issuer (Azure AD tenant) // 3. Audience (your API) // 4. Expiration // 5. Scopes/Roles

    var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
    var userName = User.Identity.Name;

    return Ok(new { userId, userName });
}

}

  <p class="practical-example-header">4. Refresh Token Flow:</p>
  <div class="code-example">
    <pre><code>public class TokenRefreshService

{ public async Task<AuthenticationResult> RefreshTokenAsync(string refreshToken) { var app = ConfidentialClientApplicationBuilder .Create(clientId) .WithClientSecret(clientSecret) .WithAuthority(authority) .Build();

    var accounts = await app.GetAccountsAsync();

    try
    {
        // Silent token acquisition using refresh token
        var result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
            .ExecuteAsync();

        return result;
    }
    catch (MsalUiRequiredException)
    {
        // Refresh token expired, user must re-authenticate
        throw new UnauthorizedException("Please sign in again");
    }
}

}

  <div class="key-concepts">
    <h4>Key Concepts:</h4>
    <ul>
      <li><strong>ID Token:</strong> Contains user information (JWT)</li>
      <li><strong>Access Token:</strong> Used to access protected resources</li>
      <li><strong>Refresh Token:</strong> Used to get new access tokens</li>
      <li><strong>Scopes:</strong> Permissions granted to the application</li>
      <li><strong>Claims:</strong> User attributes (name, email, roles)</li>
    </ul>
  </div>
</div>

<div class="part-header">Part 2: Azure Services Deep Dive</div>

<div class="question-block">
  <h3 class="question-title">Q6: What's the difference between Azure Functions and Azure WebJobs?</h3>
  <span class="answer-label">Expected Answer</span>

  <p class="content-text">Both are serverless compute options, but with key differences:</p>

  <p class="practical-example-header">Azure Functions:</p>
  <div class="code-example">
    <pre><code>public static class FunctionExample

{ // HTTP Triggered Function [FunctionName("ProcessOrder")] public static async Task<IActionResult> Run( [HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req, [Queue("orders")] IAsyncCollector<Order> orderQueue, [Table("OrdersTable")] IAsyncCollector<OrderEntity> orderTable, ILogger log) { var order = await req.Content.ReadFromJsonAsync<Order>();

    // Multiple outputs from single function
    await orderQueue.AddAsync(order);
    await orderTable.AddAsync(new OrderEntity(order));

    return new OkObjectResult($"Order {order.Id} processed");
}

// Timer Triggered Function
[FunctionName("CleanupOldData")]
public static async Task Cleanup(
    [TimerTrigger("0 0 2 * * *")] TimerInfo timer, // Runs at 2 AM daily
    ILogger log)
{
    log.LogInformation($"Cleanup executed at: {DateTime.Now}");
    // Cleanup logic
}

}

  <p class="practical-example-header">WebJobs:</p>
  <div class="code-example">
    <pre><code>public class WebJobExample

{ public static void Main() { var builder = new HostBuilder(); builder.ConfigureWebJobs(b => { b.AddAzureStorageCoreServices(); b.AddAzureStorage(); });

    var host = builder.Build();
    using (host)
    {
        host.Run();
    }
}

// Continuous WebJob
public static async Task ProcessQueueMessage(
    [QueueTrigger("orders")] Order order,
    [Blob("invoices/{rand-guid}.pdf")] Stream invoiceOutput,
    ILogger logger)
{
    logger.LogInformation($"Processing order {order.Id}");

    // Long-running process
    var invoice = await GenerateInvoiceAsync(order);
    await invoice.CopyToAsync(invoiceOutput);
}

}

  <p class="practical-example-header">Comparison Table:</p>
  <table class="comparison-table">
    <thead>
      <tr>
        <th>Feature</th>
        <th>Azure Functions</th>
        <th>Azure WebJobs</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td><strong>Hosting</strong></td>
        <td>Standalone or in App Service</td>
        <td>Only in App Service</td>
      </tr>
      <tr>
        <td><strong>Scaling</strong></td>
        <td>Auto-scales independently</td>
        <td>Scales with App Service</td>
      </tr>
      <tr>
        <td><strong>Triggers</strong></td>
        <td>HTTP, Timer, Queue, Blob, Event Hub, etc.</td>
        <td>Queue, Blob, Manual</td>
      </tr>
      <tr>
        <td><strong>Languages</strong></td>
        <td>C#, JavaScript, Python, Java, PowerShell</td>
        <td>C#, JavaScript</td>
      </tr>
      <tr>
        <td><strong>Pricing</strong></td>
        <td>Consumption or Premium plan</td>
        <td>Part of App Service plan</td>
      </tr>
      <tr>
        <td><strong>Development</strong></td>
        <td>Portal, VS, VS Code, CLI</td>
        <td>Visual Studio</td>
      </tr>
      <tr>
        <td><strong>Use Case</strong></td>
        <td>Event-driven, microservices</td>
        <td>Background tasks, continuous processing</td>
      </tr>
      <tr>
        <td><strong>Max Execution Time</strong></td>
        <td>5 min (Consumption), unlimited (Premium)</td>
        <td>Unlimited</td>
      </tr>
    </tbody>
  </table>

  <div class="when-to-use">
    <p><strong>When to Choose:</strong></p>
    <p><strong>Azure Functions:</strong> Event-driven scenarios, microservices, APIs, scheduled tasks</p>
    <p><strong>WebJobs:</strong> Long-running processes, complex scheduling, when already using App Service</p>
  </div>
</div>

<div class="question-block">
  <h3 class="question-title">Q7: How do you ensure thread safety in C#?</h3>
  <span class="answer-label">Expected Answer</span>

  <p class="content-text">Thread safety prevents race conditions when multiple threads access shared resources:</p>

  <p class="practical-example-header">1. Locking Mechanisms:</p>
  <div class="code-example">
    <pre><code>public class ThreadSafeCounter

{ private int _count; private readonly object _lockObject = new object();

// Basic lock
public void IncrementWithLock()
{
    lock (_lockObject)
    {
        _count++;
    }
}

// Monitor (equivalent to lock)
public void IncrementWithMonitor()
{
    Monitor.Enter(_lockObject);
    try
    {
        _count++;
    }
    finally
    {
        Monitor.Exit(_lockObject);
    }
}

// ReaderWriterLockSlim for read-heavy scenarios
private readonly ReaderWriterLockSlim _rwLock = new();
private List&lt;string&gt; _data = new();

public string ReadData(int index)
{
    _rwLock.EnterReadLock();
    try
    {
        return _data[index];
    }
    finally
    {
        _rwLock.ExitReadLock();
    }
}

public void WriteData(string value)
{
    _rwLock.EnterWriteLock();
    try
    {
        _data.Add(value);
    }
    finally
    {
        _rwLock.ExitWriteLock();
    }
}

}

  <p class="practical-example-header">2. Concurrent Collections:</p>
  <div class="code-example">
    <pre><code>public class ConcurrentDataStructures

{ // Thread-safe collections private readonly ConcurrentDictionary<int, string> _cache = new(); private readonly ConcurrentQueue<Task> _taskQueue = new(); private readonly ConcurrentBag<LogEntry> _logs = new();

public async Task ProcessConcurrently()
{
    // Thread-safe dictionary operations
    _cache.TryAdd(1, "value");
    _cache.AddOrUpdate(1, "new", (key, old) => "updated");

    // Producer-consumer pattern
    var bc = new BlockingCollection&lt;WorkItem&gt;(100);

    // Producer
    Task.Run(() =>
    {
        for (int i = 0; i < 10; i++)
        {
            bc.Add(new WorkItem { Id = i });
        }
        bc.CompleteAdding();
    });

    // Consumer
    Task.Run(() =>
    {
        foreach (var item in bc.GetConsumingEnumerable())
        {
            ProcessWorkItem(item);
        }
    });
}

}

  <p class="practical-example-header">3. Atomic Operations:</p>
  <div class="code-example">
    <pre><code>public class AtomicOperations

{ private int _counter; private long _total;

// Thread-safe increment without locks
public int IncrementAtomic()
{
    return Interlocked.Increment(ref _counter);
}

// Thread-safe compare and swap
public bool TryUpdate(int expected, int newValue)
{
    return Interlocked.CompareExchange(ref _counter, newValue, expected) == expected;
}

// Thread-safe addition
public void AddToTotal(long value)
{
    Interlocked.Add(ref _total, value);
}

}

  <p class="practical-example-header">4. Async/Await Patterns:</p>
  <div class="code-example">
    <pre><code>public class AsyncThreadSafety

{ private readonly SemaphoreSlim _semaphore = new(1, 1);

// Async-safe locking
public async Task&lt;string&gt; GetDataAsync()
{
    await _semaphore.WaitAsync();
    try
    {
        // Critical section
        return await FetchDataAsync();
    }
    finally
    {
        _semaphore.Release();
    }
}

// Async local storage
private static readonly AsyncLocal&lt;string&gt; _asyncLocalValue = new();

public async Task ProcessWithContext()
{
    _asyncLocalValue.Value = "ContextData";

    await Task.Run(() =>
    {
        // Value is preserved across async boundaries
        Console.WriteLine(_asyncLocalValue.Value);
    });
}

}

  <p class="practical-example-header">5. Immutable Data Structures:</p>
  <div class="code-example">
    <pre><code>public class ImmutableApproach

{ // Immutable class - inherently thread-safe public class ImmutablePerson { public string Name { get; } public int Age { get; }

    public ImmutablePerson(string name, int age)
    {
        Name = name;
        Age = age;
    }

    // Return new instance instead of modifying
    public ImmutablePerson WithAge(int newAge)
    {
        return new ImmutablePerson(Name, newAge);
    }
}

// Using System.Collections.Immutable
private ImmutableList&lt;string&gt; _list = ImmutableList&lt;string&gt;.Empty;

public void AddItem(string item)
{
    // Thread-safe: creates new list
    _list = _list.Add(item);
}

}

  <div class="best-practices">
    <h4>Best Practices:</h4>
    <ol>
      <li>Prefer immutability when possible</li>
      <li>Use concurrent collections over manual locking</li>
      <li>Keep lock sections small</li>
      <li>Avoid nested locks (deadlock risk)</li>
      <li>Use <code>volatile</code> keyword for simple flag scenarios</li>
      <li>Consider <code>ThreadLocal&lt;T&gt;</code> for thread-specific data</li>
    </ol>
  </div>
</div>

<div class="question-block">
  <h3 class="question-title">Q8: Explain async/await and when NOT to use it</h3>
  <span class="answer-label">Expected Answer</span>

  <p class="practical-example-header">How Async/Await Works:</p>
  <div class="code-example">
    <pre><code>public class AsyncAwaitExplained

{ // Async/await transforms this method into a state machine public async Task<string> GetDataAsync() { // State 0: Before first await var client = new HttpClient();

    // State 1: Awaiting HTTP call
    // Thread is released back to thread pool here
    var response = await client.GetAsync("https://api.example.com/data");

    // State 2: After HTTP call, possibly on different thread
    var content = await response.Content.ReadAsStringAsync();

    // State 3: Return result
    return content;
}

}

  <p class="practical-example-header">When TO Use Async/Await:</p>
  <div class="code-example">
    <pre><code>public class GoodAsyncUsage

{ // I/O Bound Operations public async Task<User> GetUserAsync(int id) { using var connection = new SqlConnection(connectionString); await connection.OpenAsync();

    var command = new SqlCommand("SELECT * FROM Users WHERE Id = @id", connection);
    command.Parameters.AddWithValue("@id", id);

    using var reader = await command.ExecuteReaderAsync();
    if (await reader.ReadAsync())
    {
        return MapToUser(reader);
    }
    return null;
}

// Multiple concurrent operations
public async Task&lt;Dashboard&gt; GetDashboardAsync()
{
    var userTask = GetUserAsync();
    var ordersTask = GetOrdersAsync();
    var statsTask = GetStatisticsAsync();

    await Task.WhenAll(userTask, ordersTask, statsTask);

    return new Dashboard
    {
        User = userTask.Result,
        Orders = ordersTask.Result,
        Statistics = statsTask.Result
    };
}

}

  <p class="practical-example-header">When NOT to Use Async/Await:</p>

  <div class="bad-example">
    <p class="content-text"><strong>1. CPU-Bound Operations:</strong></p>
    <div class="code-example">
      <pre><code>// ❌ BAD: No actual async operation

public async Task<int> CalculatePrimeAsync(int n) { return await Task.Run(() => { // CPU-intensive calculation // This just moves work to another thread, doesn't save resources return CalculatePrime(n); }); }

  <div class="good-example">
    <div class="code-example">
      <pre><code>// ✅ GOOD: Synchronous for CPU-bound

public int CalculatePrime(int n) { // Direct calculation return CalculatePrime(n); }

  <div class="bad-example">
    <p class="content-text"><strong>2. Simple, Fast Operations:</strong></p>
    <div class="code-example">
      <pre><code>// ❌ BAD: Async overhead for simple operation

private readonly Dictionary<int, string> _cache = new();

public async Task<string> GetFromCacheAsync(int key) { return await Task.FromResult(_cache[key]); }

  <div class="good-example">
    <div class="code-example">
      <pre><code>// ✅ GOOD: Synchronous for fast operations

public string GetFromCache(int key) { return _cache[key]; }

  <div class="bad-example">
    <p class="content-text"><strong>3. Constructor or Property:</strong></p>
    <div class="code-example">
      <pre><code>// ❌ BAD: Can't make constructor async

public MyClass() { // This blocks and can cause deadlocks InitializeAsync().GetAwaiter().GetResult(); }

  <div class="good-example">
    <div class="code-example">
      <pre><code>// ✅ GOOD: Factory pattern for async initialization

private MyClass() { }

public static async Task<MyClass> CreateAsync() { var instance = new MyClass(); await instance.InitializeAsync(); return instance; }

  <div class="bad-example">
    <p class="content-text"><strong>4. Avoiding Async All the Way:</strong></p>
    <div class="code-example">
      <pre><code>// ❌ BAD: Mixing sync and async

public void ProcessData() { var data = GetDataAsync().Result; // Can cause deadlock! Process(data); }

  <div class="good-example">
    <div class="code-example">
      <pre><code>// ✅ GOOD: Async all the way up

public async Task ProcessDataAsync() { var data = await GetDataAsync(); Process(data); }

  <div class="bad-example">
    <p class="content-text"><strong>5. Short-lived, High-frequency Operations:</strong></p>
    <div class="code-example">
      <pre><code>// ❌ BAD: Async overhead for frequent calls

public async Task LogAsync(string message) { await Task.Run(() => Console.WriteLine(message)); }

  <div class="good-example">
    <div class="code-example">
      <pre><code>// ✅ GOOD: Use synchronous or batch

private readonly Channel<string> _logChannel = Channel.CreateUnbounded<string>();

public void Log(string message) { _logChannel.Writer.TryWrite(message); }

// Background service processes batches public async Task ProcessLogsAsync() { await foreach (var message in _logChannel.Reader.ReadAllAsync()) { Console.WriteLine(message); } }

  <p class="practical-example-header">Common Pitfalls:</p>
  <div class="code-example">
    <pre><code>public class AsyncPitfalls

{ // ❌ Async void (except event handlers) public async void BadMethod() { await Task.Delay(1000); // Exceptions here crash the application }

// ✅ Return Task
public async Task GoodMethod()
{
    await Task.Delay(1000);
}

// ❌ Unnecessary async/await
public async Task&lt;string&gt; UnnecessaryAsync()
{
    return await GetStringAsync();
}

// ✅ Direct return
public Task&lt;string&gt; DirectReturn()
{
    return GetStringAsync();
}

// ⚠️ ConfigureAwait for libraries
public async Task LibraryMethod()
{
    await SomeOperationAsync().ConfigureAwait(false);
    // Don't capture SynchronizationContext in libraries
}

}

<div class="part-header">Part 3: System Design & Architecture Questions</div>

<div class="question-block">
  <h3 class="question-title">Q9: How would you migrate a monolithic application to Azure?</h3>
  <span class="answer-label">Expected Answer</span>

  <p class="content-text"><strong>Step-by-Step Migration Strategy:</strong></p>

  <p class="practical-example-header">Phase 1: Assessment & Planning</p>
  <div class="code-example">
    <pre><code>public class ApplicationAssessment

{ public class MigrationReadiness { public Dictionary<string, ComponentAnalysis> Components { get; set; }

    public class ComponentAnalysis
    {
        public string Name { get; set; }
        public List&lt;string&gt; Dependencies { get; set; }
        public int CouplingScore { get; set; } // 1-10
        public bool IsStateless { get; set; }
        public string DataStore { get; set; }
        public List&lt;string&gt; ExternalIntegrations { get; set; }
    }

    public MigrationStrategy DetermineStrategy()
    {
        // Analyze components for:
        // 1. Tight coupling (database, shared state)
        // 2. Business boundaries
        // 3. Scalability requirements
        // 4. Technology constraints

        return new MigrationStrategy
        {
            Pattern = "StranglerFig", // or "BigBang", "BranchByAbstraction"
            Priority = "CustomerFacing", // Start with edge services
            Timeline = "6-12 months"
        };
    }
}

}

  <p class="practical-example-header">Phase 2: Strangler Fig Pattern Implementation</p>
  <div class="code-example">
    <pre><code>// Step 1: Add API Gateway

public class ApiGatewayConfiguration { public void Configure(IApplicationBuilder app) { app.UseOcelot(async (context, next) => { // Route to monolith or new microservices var path = context.Request.Path.Value;

        if (path.StartsWith("/api/users"))
        {
            // Route to new User microservice
            context.Request.Path = "/users" + path.Substring(10);
            await next.Invoke();
        }
        else
        {
            // Route to monolith
            context.Request.Host = new HostString("monolith.app");
            await next.Invoke();
        }
    });
}

}

// Step 2: Extract first microservice public class UserServiceExtraction { // Original monolith code public class MonolithUserService { private readonly AppDbContext _context;

    public User GetUser(int id)
    {
        return _context.Users
            .Include(u => u.Orders) // Tight coupling
            .FirstOrDefault(u => u.Id == id);
    }
}

// New microservice
public class UserMicroservice
{
    private readonly UserDbContext _userContext;
    private readonly IOrderServiceClient _orderService;

    public async Task&lt;UserDto&gt; GetUserAsync(int id)
    {
        var user = await _userContext.Users.FindAsync(id);

        // Call Order service for order data
        var orders = await _orderService.GetUserOrdersAsync(id);

        return new UserDto
        {
            Id = user.Id,
            Name = user.Name,
            Orders = orders
        };
    }
}

}

  <p class="practical-example-header">Phase 3: Data Migration Strategy</p>
  <div class="code-example">
    <pre><code>public class DataMigrationStrategy

{ // Option 1: Shared Database Anti-pattern (temporary) public class SharedDatabaseApproach { // Both monolith and microservice access same DB // Use for gradual migration public void ConfigureServices(IServiceCollection services) { services.AddDbContext<SharedDbContext>(options => options.UseSqlServer(sharedConnectionString)); } }

// Option 2: Database per Service with Sync
public class DatabasePerService
{
    public async Task MigrateDataAsync()
    {
        // 1. Dual writes during transition
        await WriteToMonolithDb(data);
        await WriteToMicroserviceDb(data);

        // 2. Sync historical data
        var batchSize = 1000;
        var offset = 0;

        while (true)
        {
            var batch = await GetMonolithData(offset, batchSize);
            if (!batch.Any()) break;

            await WriteBatchToNewDb(batch);
            offset += batchSize;

            // Track progress
            await UpdateMigrationProgress(offset);
        }
    }
}

}

  <p class="practical-example-header">Phase 4: Azure Service Selection</p>
  <div class="yaml-block">

# Azure Architecture for Microservices

## Compute:

## Data:

## Messaging:

## API Management:

## Monitoring:

public class DeploymentConfiguration { public string GeneratePipeline() { return @" trigger:

  • main

stages:

{ public class AzureComponents { // Multi-region deployment public List<string> Regions = new() { "East US", "West Europe" };

    // Traffic Management
    public string TrafficManager = "Azure Front Door"; // Global load balancing

    // Compute Layer
    public ComputeConfiguration Compute = new()
    {
        Primary = "Azure Kubernetes Service (AKS)",
        AutoScaling = true,
        MinReplicas = 3,
        MaxReplicas = 100,
        AvailabilityZones = new[] { "1", "2", "3" }
    };

    // Data Layer
    public DataConfiguration Data = new()
    {
        Database = "Cosmos DB with multi-region writes",
        Cache = "Azure Cache for Redis Premium",
        Storage = "Geo-redundant Storage (GRS)",
        CDN = "Azure CDN for static content"
    };
}

}

  <p class="practical-example-header">Implementation Details:</p>

  <p class="content-text"><strong>1. Frontend Layer (High Availability)</strong></p>
  <div class="code-example">
    <pre><code>// Azure Front Door configuration

public class FrontDoorConfiguration { public void ConfigureGlobalLoadBalancing() { var frontDoor = new FrontDoorConfig { BackendPools = new[] { new BackendPool { Name = "primary-pool", Backends = new[] { new Backend { Address = "eastus.app.com", Priority = 1, Weight = 50 }, new Backend { Address = "westeu.app.com", Priority = 1, Weight = 50 } }, HealthProbe = new HealthProbe { Path = "/health", Interval = TimeSpan.FromSeconds(30), Timeout = TimeSpan.FromSeconds(10) } } }, RoutingRules = new[] { new RoutingRule { Pattern = "/*", BackendPool = "primary-pool", CacheEnabled = true, CacheDuration = TimeSpan.FromMinutes(5) } } }; } }

  <p class="content-text"><strong>2. API Layer (Microservices)</strong></p>
  <div class="code-example">
    <pre><code>// Product Service with resilience

public class ProductService { private readonly IHttpClientFactory _httpClientFactory; private readonly IMemoryCache _cache;

public async Task&lt;Product&gt; GetProductAsync(int id)
{
    // Multi-layer caching
    if (_cache.TryGetValue($"product_{id}", out Product cached))
    {
        return cached;
    }

    // Circuit breaker pattern
    var httpClient = _httpClientFactory.CreateClient("ProductApi");

    var policy = Policy
        .Handle&lt;HttpRequestException&gt;()
        .OrResult&lt;HttpResponseMessage&gt;(r => !r.IsSuccessStatusCode)
        .WaitAndRetryAsync(
            3,
            retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
            onRetry: (outcome, timespan, retryCount, context) =>
            {
                _logger.LogWarning($"Retry {retryCount} after {timespan}");
            });

    var response = await policy.ExecuteAsync(async () =>
        await httpClient.GetAsync($"/api/products/{id}"));

    if (response.IsSuccessStatusCode)
    {
        var product = await response.Content.ReadFromJsonAsync&lt;Product&gt;();
        _cache.Set($"product_{id}", product, TimeSpan.FromMinutes(5));
        return product;
    }

    // Fallback to Cosmos DB read
    return await GetFromDatabaseAsync(id);
}

}

  <p class="content-text"><strong>3. Data Layer (Multi-Region Cosmos DB)</strong></p>
  <div class="code-example">
    <pre><code>public class CosmosDbConfiguration

{ public void ConfigureHighAvailability() { var cosmosClient = new CosmosClientBuilder(connectionString) .WithApplicationRegion(Regions.EastUS) // Preferred region .WithApplicationPreferredRegions(new[] { Regions.EastUS, Regions.WestEurope, Regions.SoutheastAsia }) .WithConnectionModeDirect() // Better performance .WithBulkExecution(true) // Bulk operations .WithConsistencyLevel(ConsistencyLevel.Session) // Balance consistency/performance .Build(); }

public async Task&lt;Order&gt; CreateOrderWithSagaAsync(Order order)
{
    var container = cosmosClient.GetContainer("ecommerce", "orders");

    // Implement idempotency
    order.Id = order.IdempotencyKey ?? Guid.NewGuid().ToString();

    try
    {
        // Transactional batch for consistency
        var batch = container.CreateTransactionalBatch(
            new PartitionKey(order.CustomerId))
            .CreateItem(order)
            .CreateItem(new Inventory { ProductId = order.ProductId, Quantity = -1 });

        var response = await batch.ExecuteAsync();

        if (response.IsSuccessStatusCode)
        {
            // Publish to Service Bus for order processing
            await _serviceBus.SendMessageAsync(new ServiceBusMessage(
                JsonSerializer.Serialize(order))
            {
                Subject = "OrderCreated",
                SessionId = order.CustomerId // For FIFO processing
            });
        }

        return order;
    }
    catch (CosmosException ex) when (ex.StatusCode == HttpStatusCode.Conflict)
    {
        // Idempotent - order already exists
        return await GetOrderAsync(order.Id);
    }
}

}

  <p class="content-text"><strong>4. Messaging Layer (Service Bus)</strong></p>
  <div class="code-example">
    <pre><code>public class OrderProcessingService

{ public void ConfigureServiceBus() { var client = new ServiceBusClient(connectionString, new ServiceBusClientOptions { TransportType = ServiceBusTransportType.AmqpWebSockets, RetryOptions = new ServiceBusRetryOptions { MaxRetries = 3, Delay = TimeSpan.FromSeconds(1), MaxDelay = TimeSpan.FromSeconds(10), Mode = ServiceBusRetryMode.Exponential } });

    // Configure processor with session for ordered processing
    var processor = client.CreateSessionProcessor("orders", new ServiceBusSessionProcessorOptions
    {
        MaxConcurrentSessions = 100,
        MaxConcurrentCallsPerSession = 1, // Ensure order
        SessionIdleTimeout = TimeSpan.FromMinutes(5)
    });
}

}

  <p class="content-text"><strong>5. Monitoring & Observability</strong></p>
  <div class="code-example">
    <pre><code>public class ObservabilityConfiguration

{ public void ConfigureApplicationInsights(IServiceCollection services) { services.AddApplicationInsightsTelemetry(); services.AddSingleton<ITelemetryInitializer, CustomTelemetryInitializer>();

    // Custom metrics
    services.Configure&lt;TelemetryConfiguration&gt;((o) =>
    {
        o.TelemetryProcessorChainBuilder
            .Use((next) => new AdaptiveSamplingTelemetryProcessor(next))
            .Build();
    });
}

public class CustomTelemetryInitializer : ITelemetryInitializer
{
    public void Initialize(ITelemetry telemetry)
    {
        telemetry.Context.Properties["Environment"] = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
        telemetry.Context.Properties["Region"] = Environment.GetEnvironmentVariable("AZURE_REGION");

        if (telemetry is RequestTelemetry request)
        {
            // Add custom dimensions
            request.Properties["UserId"] = HttpContext.Current?.User?.Identity?.Name;
        }
    }
}

}

  <p class="practical-example-header">Disaster Recovery Strategy:</p>
  <div class="yaml-block">

RTO (Recovery Time Objective): 5 minutes RPO (Recovery Point Objective): 1 minute

Strategies:

  1. Active-Active: Both regions serve traffic
  2. Database: Cosmos DB with multi-region writes
  3. Storage: Geo-redundant storage with RA-GRS
  4. Backup: Automated backups every hour
  5. Failover: Automated via Azure Front Door health probes
  6. Testing: Monthly DR drills
    Part 4: Best Practices & Advanced Topics

    Q11: How do you optimize LINQ queries for performance?

    Expected Answer

    Common LINQ Performance Issues and Solutions:

    public class LinqOptimization

{ private readonly AppDbContext _context;

// ❌ BAD: N+1 Query Problem
public void BadExample()
{
    var orders = _context.Orders.ToList();
    foreach (var order in orders)
    {
        // Each iteration triggers a database query
        Console.WriteLine(order.Customer.Name);
    }
}

// ✅ GOOD: Eager Loading
public void GoodExample()
{
    var orders = _context.Orders
        .Include(o => o.Customer)
        .ToList();
}

// ❌ BAD: Loading unnecessary data
public List&lt;string&gt; GetProductNames()
{
    return _context.Products
        .ToList() // Loads entire product objects
        .Select(p => p.Name)
        .ToList();
}

// ✅ GOOD: Project only needed fields
public List&lt;string&gt; GetProductNamesOptimized()
{
    return _context.Products
        .Select(p => p.Name) // SQL: SELECT Name FROM Products
        .ToList();
}

// ❌ BAD: Multiple database round trips
public async Task&lt;DashboardData&gt; GetDashboardDataSlow()
{
    var totalOrders = await _context.Orders.CountAsync();
    var pendingOrders = await _context.Orders.Where(o => o.Status == "Pending").CountAsync();
    var totalRevenue = await _context.Orders.SumAsync(o => o.Total);

    return new DashboardData { TotalOrders = totalOrders, PendingOrders = pendingOrders, Revenue = totalRevenue };
}

// ✅ GOOD: Single query with aggregation
public async Task&lt;DashboardData&gt; GetDashboardDataOptimized()
{
    return await _context.Orders
        .GroupBy(o => 1) // Group all into single group
        .Select(g => new DashboardData
        {
            TotalOrders = g.Count(),
            PendingOrders = g.Count(o => o.Status == "Pending"),
            Revenue = g.Sum(o => o.Total)
        })
        .FirstOrDefaultAsync();
}

// Compiled Queries for frequently used queries
private static readonly Func&lt;AppDbContext, int, Task&lt;Product&gt;&gt; GetProductById =
    EF.CompileAsyncQuery((AppDbContext context, int id) =>
        context.Products.FirstOrDefault(p => p.Id == id));

public Task&lt;Product&gt; GetProductByIdFast(int id)
{
    return GetProductById(_context, id);
}

// AsNoTracking for read-only operations
public async Task&lt;List&lt;ProductDto&gt;&gt; GetProductsReadOnly()
{
    return await _context.Products
        .AsNoTracking() // Don't track entities for change detection
        .Where(p => p.IsActive)
        .Select(p => new ProductDto { Id = p.Id, Name = p.Name })
        .ToListAsync();
}

}

<div class="question-block">
  <h3 class="question-title">Q12: Implement a real-time notification system using Azure services</h3>
  <span class="answer-label">Expected Answer</span>

  <p class="content-text">Complete implementation using SignalR and Azure Services</p>

  <p class="practical-example-header">1. SignalR Hub</p>
  <div class="code-example">
    <pre><code>public class NotificationHub : Hub

{ private readonly IConnectionManager _connectionManager;

public override async Task OnConnectedAsync()
{
    var userId = Context.User.Identity.Name;
    await _connectionManager.AddConnectionAsync(userId, Context.ConnectionId);

    await Groups.AddToGroupAsync(Context.ConnectionId, $"user-{userId}");
    await base.OnConnectedAsync();
}

public async Task SubscribeToCategory(string category)
{
    await Groups.AddToGroupAsync(Context.ConnectionId, $"category-{category}");
}

}

  <p class="practical-example-header">2. Service Bus Message Handler</p>
  <div class="code-example">
    <pre><code>public class NotificationProcessor : IHostedService

{ private readonly ServiceBusProcessor _processor; private readonly IHubContext<NotificationHub> _hubContext;

public async Task StartAsync(CancellationToken cancellationToken)
{
    _processor.ProcessMessageAsync += HandleMessageAsync;
    _processor.ProcessErrorAsync += HandleErrorAsync;
    await _processor.StartProcessingAsync(cancellationToken);
}

private async Task HandleMessageAsync(ProcessMessageEventArgs args)
{
    var notification = JsonSerializer.Deserialize&lt;Notification&gt;(args.Message.Body);

    switch (notification.Type)
    {
        case NotificationType.User:
            await _hubContext.Clients.Group($"user-{notification.UserId}")
                .SendAsync("ReceiveNotification", notification);
            break;

        case NotificationType.Broadcast:
            await _hubContext.Clients.All
                .SendAsync("ReceiveNotification", notification);
            break;

        case NotificationType.Category:
            await _hubContext.Clients.Group($"category-{notification.Category}")
                .SendAsync("ReceiveNotification", notification);
            break;
    }

    await args.CompleteMessageAsync(args.Message);
}

}

  <p class="practical-example-header">3. Notification Service</p>
  <div class="code-example">
    <pre><code>public class NotificationService

{ private readonly ServiceBusSender _sender; private readonly INotificationRepository _repository;

public async Task SendNotificationAsync(Notification notification)
{
    // Save to database for persistence
    await _repository.SaveAsync(notification);

    // Send to Service Bus for real-time delivery
    var message = new ServiceBusMessage(JsonSerializer.Serialize(notification))
    {
        Subject = notification.Type.ToString(),
        ContentType = "application/json",
        TimeToLive = TimeSpan.FromHours(1)
    };

    await _sender.SendMessageAsync(message);
}

// Batch notifications for efficiency
public async Task SendBatchNotificationsAsync(List&lt;Notification&gt; notifications)
{
    var messages = notifications.Select(n => new ServiceBusMessage(
        JsonSerializer.Serialize(n))
    {
        Subject = n.Type.ToString()
    }).ToList();

    await _sender.SendMessagesAsync(messages);
}

}

  <p class="practical-example-header">4. Push Notifications (Mobile)</p>
  <div class="code-example">
    <pre><code>public class PushNotificationService

{ private readonly NotificationHubClient _hubClient;

public async Task SendPushNotificationAsync(string userId, string message)
{
    var notification = new Dictionary&lt;string, string&gt;
    {
        { "message", message },
        { "badge", "1" }
    };

    // Send to specific user's devices
    await _hubClient.SendTemplateNotificationAsync(notification, $"userId:{userId}");
}

}

  <p class="practical-example-header">5. Client-side (JavaScript/TypeScript)</p>
  <div class="code-example">
    <pre><code>const connection = new signalR.HubConnectionBuilder()
.withUrl('/notificationHub')
.withAutomaticReconnect([0, 2000, 10000, 30000])
.build();

connection.on('ReceiveNotification', (notification) => { // Handle notification showToast(notification); updateNotificationBadge();

// Store in IndexedDB for offline access
await db.notifications.add(notification);

});

// Reconnection handling connection.onreconnecting(error => { console.log('Reconnecting...', error); showConnectionStatus('reconnecting'); });

connection.onreconnected(connectionId => { console.log('Reconnected', connectionId); showConnectionStatus('connected');

// Re-subscribe to categories
subscribeToCategories();

});

await connection.start();

  <p class="practical-example-header">6. Scaling Configuration</p>
  <div class="code-example">
    <pre><code>public class ScalingConfiguration

{ public void ConfigureServices(IServiceCollection services) { // Use Azure SignalR Service for scaling services.AddSignalR() .AddAzureSignalR(options => { options.ConnectionString = Configuration["Azure:SignalR:ConnectionString"]; options.ServerStickyMode = ServerStickyMode.Required; });

    // Redis backplane for multiple servers
    services.AddStackExchangeRedisCache(options =>
    {
        options.Configuration = Configuration["Redis:ConnectionString"];
    });
}

}

<div class="conclusion-section">
  <h2>Conclusion</h2>
  <p class="content-text">This study guide covers the essential topics for .NET Azure developer interviews. Remember:</p>
  <ol>
    <li><strong>Understand the concepts deeply</strong> - Don't just memorize answers</li>
    <li><strong>Practice coding</strong> - Implement these patterns yourself</li>
    <li><strong>Know the trade-offs</strong> - Every solution has pros and cons</li>
    <li><strong>Stay current</strong> - Azure services evolve rapidly</li>
    <li><strong>Think about scale</strong> - Consider performance and cost implications</li>
  </ol>
  <p class="content-text" style="margin-top: 25px; font-style: italic;">Focus on understanding the "why" behind each solution, as interviewers value problem-solving approach over memorized answers. Good luck with your interview preparation!</p>
</div>