Did you know? The C# language has a GOTO statement? It sure does. This is a case of “just because you could doesn’t mean you should”.
Welcome to dotInsights by JetBrains! This newsletter is the home for recent .NET and software development related information.
🌟 Featured Content
This month’s featured content is from Chris Woodruff! Chris has been at the forefront of software development since before the first .COM boom, building a career that spans enterprise web development, cloud solutions, software analytics, and developer relations. As an Architect, he applies his deep technical expertise to tackle complex challenges, with a particular focus on API design and scalable architectures. He is recognized as a Microsoft MVP specializing in .NET and Web Development. Woody’s impact extends beyond his professional responsibilities; he is a dedicated mentor and educator, teaching courses that help individuals transition into tech careers. His passion for sharing knowledge has made him a sought-after speaker at international conferences, where he discusses topics such as database development, web APIs, and software architecture. He contributes to the developer community by co-hosting The Breakpoint Show podcast and creating content that aids engineers in refining their skills.
Entity Framework Core (EF Core) has emerged as the preferred Object-Relational Mapping (ORM) tool for modern .NET developers. However, effectively utilizing it requires more than just familiarity with methods like .Add() and .SaveChanges(). This concise newsletter summarizes the essential insights from a full-day EF Core workshop (contact Woody for details below if interested), equipping you with the knowledge necessary to build fast, secure, and scalable data access layers.
Getting Started with EF Core EF Core is a lightweight, extensible, and high-performance data access framework. It supports a clean code-first approach while allowing database-first flexibility when needed.
Key Concepts: ✅ DbContext is your gateway to the database. It manages connections change tracking, and query execution. ✅ Use DbSet<T> to represent your entity collections. ✅ Code-First is ideal for domain-driven development; use Fluent API to fine-tune schema mappings. 💡Pro Tip: Always register your DbContext as Scoped. Avoid Singleton lifetimes to prevent memory issues and concurrency errors.
Modeling Relationships Like a Pro EF Core handles common relationship types easily, but it’s up to you to configure them correctly.
Modeling Must-Knows: ✅ Define one-to-many with .HasMany().WithOne() ✅ Use explicit foreign keys in your model for clarity. ✅ Prefer eager loading (.Include()) for web APIs to avoid runtime surprises. 💡Pro Tip: Don’t rely on lazy loading in APIs. It hides performance issues and can cause excessive database queries.
Querying with Power and Precision LINQ is a powerful abstraction, but be intentional.
Performance-First Query Tips: ✅ Use .Select() to shape the result into DTOs, avoid sending entire entities. ✅ Apply .AsNoTracking() for read-only queries to reduce memory use. ✅ Chain .Where() and .OrderBy() before projection to reduce query size. 💡Pro Tip: Avoid over-fetching by skipping unnecessary .Include() chains. Smaller queries are faster queries.
SQL Server: Tune What EF Core Generates You’re still writing SQL, it’s just hidden behind LINQ.
SQL Server Optimization: ✅ Use SSMS to inspect EF-generated SQL. ✅ Read execution plans to diagnose slow queries. ✅ Tune indexes based on frequent query filters or sorts. ✅ Leverage Query Store to monitor historical query behavior 💡Pro Tip: Computed columns and filtered indexes can supercharge performance when used intentionally.
Secure Your Data Layer EF Core doesn’t protect you from bad design. Data security must be implemented in your access layer.
Security Strategies: ✅ Use DTOs to prevent overposting. ✅ Filter by user role or claim inside the query, not afterward. ✅ Never interpolate raw SQL, always parameterize inputs. ✅ Store secrets securely: Use User Secrets in dev, Managed Identity in Azure. 💡Pro Tip: Your DbContext is an attack surface. Secure it like you would any API.
Testing EF Core with Confidence Testing EF Core doesn’t have to be painful, use the right tools.
Approach by Test Type: ✅ Use In-Memory provider for fast unit tests, but be aware it behaves differently from SQL Server. ✅ Prefer SQLite in-memory for a closer match to production. ✅ Use Testcontainers or local SQL Server for full integration testing. 💡Pro Tip: Seed data should be scenario-specific and reset between tests. Use Respawn or EF-based seeding for consistency.
Scaling for the Cloud Cloud-readiness means EF Core must handle concurrency, resiliency, and high throughput.
Cloud-Ready Practices: ✅ Use DbContextPool for high-performance APIs. ✅ Configure retry logic with EnableRetryOnFailure(), and even better, learn and use Polly, which is a library for .NET designed for resilience and transient-fault handling. It enables developers to express policies such as Retry, Circuit Breaker, Timeout, Bulkhead Isolation, and Fallback in a fluent, thread-safe manner. ✅ Apply distributed caching at the service layer, not the EF level. ✅ Use sharded/multi-tenant strategies carefully: filtered queries, schema separation, or even DB-per-tenant. 💡Pro Tip: Azure SQL + EF Core is a battle-tested combo, just don’t forget to tune your retry strategies and monitor connection health.
Common Pitfalls and How to Avoid Them Even experienced developers can fall into subtle traps when working with EF Core. Here are some of the most common mistakes, and how to dodge them in your projects.
❌ Lazy Loading in APIs Lazy loading can cause unexpected multiple queries per request. In web APIs, it often results in the dreaded N+1 problem. ✅ Use Eager Loading or Projections Explicitly load related data with .Include() or shape the query using .Select() and DTOs.
❌ Leaking Entities to the Client Exposing EF entities directly in your controllers or UI tightly couples your domain to your database schema. ✅ Use DTOs or ViewModels Map to dedicated types that represent what the consumer needs. Nothing more, nothing less.
❌ Overusing .Include() Chains Deep includes may look convenient, but can result in massive SQL joins and redundant data loading. ✅ Load Only What You Need Be intentional. Use shaped queries and projections for complex object graphs.
❌ Ignoring Execution Plans and SQL Output If you’re not inspecting the SQL your LINQ generates, you’re flying blind. ✅ Use SSMS and Query Store Always review generated SQL for critical paths. Use SQL Server tooling to optimize indexes and execution plans.
Each month we feature tutorials or tips from our .NET Guide.
Azure Functions
Developing and managing cloud solutions often requires a seamless and efficient workflow. Rider, with its robust integration and tooling, empowers developers to build, debug, and deploy Azure Functions effortlessly. Whether you’re handling event-driven serverless functions or scaling cloud-native applications, Rider offers the tools to identify issues early, ensure smooth debugging, and optimize your deployment process.