Meta tags:
description= Master EF Core 8 for efficient data access in .NET 8 apps. Learn models, migrations, LINQ, relationships, transactions, performance tuning, testing, and provider switching. Build a Todo API from basic CRUD to production-ready patterns with SQLite in dev and PostgreSQL (or SQL Server) in prod.;
keywords= EF Core 8 tutorial, .NET 8 data access, Entity Framework Core, code-first migrations, LINQ queries, JSON columns, batching, raw SQL, relationships, performance optimization, in-memory testing, PostgreSQL EF Core, SQL Server;
author= dotnet-guide.com;
Headings (most frequently used words):
to, core, ef, with, provider, queries, net, many, in, dbcontext, testing, data, linq, concurrency, and, create, your, migration, for, vs, when, fundamentals, access, what, project, seeding, asp, transactions, performance, database, resources, related, tutorials, raw, sql, compiled, add, packages, entity, configuration, relationship, explicit, basic, filtering, pagination, query, best, features, inmemory, use, how, modern, table, of, contents, new, setup, creation, models, migrations, relationships, navigation, practice, integrating, apis, optimization, switching, providers, next, steps, frequently, asked, questions, json, columns, smarter, batching, improvements, enhancements, install, sdk, tools, configure, program, cs, connection, string, define, model, fluent, api, value, objects, owned, types, first, file, structure, commands, one, join, loading, strategies, sorting, projection, dtos, advanced, dynamic, crud, endpoints, support, error, handling, optimistic, retry, policies, polly, asnotracking, read, only, solving, problems, interceptors, executeupdate, executedelete, practices, multi, specific, environment, based, selection, sqlite, memory, factory, pattern, alternative, on, dotnet, guide, com, official, documentation, github, example, projects, community, nuget, meaningfully, better, repositories, direct, profile, slow, is, reliable, relational, behaviors, prefer, over, handle, very, large, result, sets, dapper, which, cloud, deployment, 12, language, essentials,
Text of the page (most frequently used words):
todo (111), todos (102), for (90), public (86), await (78), var (74), and (71), context (65), with (61), core (57), new (55), title (50), query (48), copy (48), #string (46), set (46), data (44), get (44), use (43), sql (42), datetime (38), entity (37), appdbcontext (37), isdone (37), database (36), queries (34), int (34), options (32), provider (29), dotnet (29), where (28), sqlite (28), builder (27), duedate (25), category (25), return (23), tolistasync (23), postgresql (22), migrations (22), configuration (22), microsoft (21), class (21), async (21), modelbuilder (21), you (20), server (20), net (18), the (18), dbcontext (18), migration (18), app (18), createdat (17), utcnow (17), request (17), your (16), json (16), from (16), loading (16), entityframeworkcore (16), using (16), property (16), tags (16), results (16), api (15), production (15), add (15), compiled (15), savechangesasync (15), null (15), features (14), performance (14), when (14), columns (14), select (14), include (14), join (14), table (14), services (13), complex (13), memory (13), linq (13), tag (13), empty (13), concurrency (12), _context (12), categoryid (12), better (11), support (11), transactions (11), that (11), update (11), access (11), task (11), column (11), name (11), many (11), tracking (10), only (10), multiple (10), tools (10), through (10), connection (10), assert (10), create (10), findasync (10), test (10), code (10), pagesize (10), navigation (10), build (9), apis (9), providers (9), relationships (9), without (9), specific (9), testing (9), false (9), void (9), now (9), default (9), explicit (9), list (9), model (9), models (8), read (8), load (8), inmemory (8), relational (8), development (8), generated (8), run (8), install (8), usesqlite (8), true (8), environment (8), override (8), categories (8), applications (7), need (7), project (7), raw (7), operations (7), asnotracking (7), not (7), updatedat (7), entry (7), bool (7), todoid (7), protected (7), transaction (7), page (7), migrationbuilder (7), nullable (7), tutorials (6), related (6), change (6), dtos (6), like (6), foreign (6), tests (6), batching (6), handling (6), com (6), dbcontextoptionsbuilder (6), service (6), count (6), context1 (6), getconnectionstring (6), filtering (6), orderby (6), changes (6), 200 (6), value (6), totalcount (6), seeding (6), fundamentals (5), modern (5), azure (5), based (5), deployment (5), design (5), most (5), into (5), tables (5), doesn (5), constraints (5), but (5), mapping (5), faster (5), what (5), github (5), package (5), sqlserver (5), packages (5), avoid (5), tip (5), same (5), modified (5), private (5), readonly (5), _connection (5), adddbcontext (5), program (5), bulk (5), efficient (5), split (5), scope (5), one (5), record (5), address (5), asp (4), high (4), provides (4), all (4), scenarios (4), consider (4), best (4), full (4), productivity (4), dapper (4), over (4), approach (4), pagination (4), this (4), common (4), web (4), reduce (4), needed (4), endpoints (4), foreach (4), skip (4), how (4), result (4), search (4), proper (4), type (4), prefer (4), key (4), see (4), problems (4), repeated (4), console (4), enablesensitivedatalogging (4), work (4), entities (4), switch (4), smarter (4), round (4), trips (4), improved (4), lts (4), guide (4), basic (4), advanced (4), example (4), learn (4), keys (4), fact (4), arrange (4), act (4), sqliteconnection (4), static (4), incompletetodos (4), setup (4), source (4), types (4), functions (4), case (4), date (4), throw (4), can (4), indexes (4), separate (4), solution (4), optionsbuilder (4), automatically (4), fluent (4), notfound (4), try (4), error (4), hasvalue (4), countasync (4), items (4), properties (4), lazy (4), virtual (4), collection (4), todotag (4), withmany (4), first (4), hasmaxlength (4), hasindex (4), master (3), automatic (3), across (3), serverless (3), crud (3), heavy (3), control (3), minimal (3), large (3), early (3), transfer (3), than (3), take (3), handle (3), business (3), logic (3), execution (3), parameterization (3), keep (3), maintainability (3), semantics (3), fast (3), unit (3), behavior (3), real (3), slower (3), including (3), triggers (3), enable (3), logging (3), store (3), writeline (3), simple (3), brings (3), savechanges (3), november (3), 2026 (3), throughput (3), improvements (3), frequently (3), questions (3), next (3), npgsql (3), nuget (3), framework (3), resources (3), clone (3), version (3), appsettings (3), documentation (3), strategy (3), contexts (3), datasource (3), context2 (3), user (3), single (3), savedtodo (3), dispose (3), between (3), selection (3), isdevelopment (3), staging (3), usesqlserver (3), metadata (3), temporal (3), hasdefaultvaluesql (3), connectionstring (3), break (3), connections (3), multi (3), develop (3), them (3), order (3), fields (3), updates (3), cache (3), projection (3), never (3), practices (3), delete (3), eventdata (3), register (3), serviceprovider (3), problem (3), polly (3), rowversion (3), updatetodorequest (3), nocontent (3), catch (3), newcategoryid (3), newcategory (3), safe (3), createtodorequest (3), mapget (3), remove (3), searchterm (3), categoryname (3), pagedresult (3), write (3), eager (3), optional (3), tagid (3), haskey (3), hasone (3), hasforeignkey (3), conventions (3), script (3), initialcreate (3), hasdata (3), onmodelcreating (3), databaseseeder (3), classes (3), todoconfiguration (3), configure (3), while (3), sdk (3), performant (3), ready (3), then (3), essentials (2), blazor (2), apps (2), language (2), managed (2), scaling (2), works (2), choose (2), cloud (2), both (2), have (2), per (2), stack (2), domain (2), driven (2), rich (2), focused (2), overhead (2), very (2), background (2), rather (2), generates (2), stored (2), procedures (2), text (2), injection (2), standard (2), safety (2), flexibility (2), fromsqlraw (2), matter (2), reserve (2), reliable (2), sensitive (2), parameter (2), values (2), profiler (2), fix (2), measure (2), application (2), pg_stat_statements (2), logto (2), profile (2), directly (2), pattern (2), repository (2), isolation (2), rules (2), often (2), creates (2), start (2), repositories (2), reduces (2), enhancements (2), aligns (2), upgrade (2), asked (2), view (2), time (2), community (2), git (2), here (2), steps (2), don (2), dbset (2), more (2), todoservicetests (2), addrange (2), todoservice (2), equal (2), must (2), todo1 (2), todo2 (2), dbupdateconcurrencyexception (2), testdatabasefactory (2), createinmemorydatabase (2), open (2), ensurecreated (2), createseededdatabase (2), seed (2), factory (2), todorepositorytests (2), firstordefaultasync (2), each (2), optimizations (2), local (2), else (2), usenpgsql (2), 2016 (2), hascolumntype (2), totable (2), adddays (2), array (2), english (2), term (2), file (2), good (2), small (2), sqliteoptions (2), databaseprovider (2), connectionstrings (2), localhost (2), todosdb (2), changing (2), switching (2), trade (2), they (2), pre (2), hot (2), dynamic (2), strategic (2), executedelete (2), executeupdate (2), reference (2), entire (2), always (2), caching (2), setters (2), setproperty (2), softdeleteinterceptor (2), interceptionresult (2), state (2), entitystate (2), isoftdelete (2), isdeleted (2), deletedat (2), interceptor (2), define (2), func (2), _gettodobyid (2), compileasyncquery (2), iasyncenumerable (2), _getoverduetodos (2), comments (2), bad (2), onconfiguring (2), bottlenecks (2), optimization (2), sqloptions (2), timespan (2), fromseconds (2), retrypolicy (2), dbupdateexception (2), retryattempt (2), math (2), retry (2), mapput (2), message (2), notfoundexception (2), found (2), scoped (2), lifetime (2), long (2), instead (2), warning (2), mappost (2), validation (2), isnullorwhitespace (2), validationproblem (2), dictionary (2), required (2), created (2), asqueryable (2), integrating (2), any (2), conditional (2), completedcount (2), todoswithcategories (2), todosummarydto (2), todowithcategorydto (2), patterns (2), practice (2), know (2), extra (2), loadasync (2), isactive (2), strategies (2), custom (2), relationship (2), generate (2), bundle (2), commands (2), seedasync (2), seeder (2), apply (2), applying (2), terminal (2), schema (2), ientitytypeconfiguration (2), street (2), city (2), customer (2), shippingaddress (2), objects (2), isrequired (2), hasconversion (2), stringsplitoptions (2), removeemptyentries (2), tolist (2), information (2), defaultconnection (2), todoapiefcore (2), download (2), creation (2), end (2), diagnose (2), ship (2), comprehensive (2), tutorial (2), scratch (2), starting (2), locally (2), simplicity (2), pairs (2), deliver (2), keeping (2), back, getting, started, components, integrates, seamlessly, offers, backups, built, availability, easiest, choice, via, aws, rds, excellent, strong, lower, costs, major, clouds, platform, budget, feature, needs, mature, aurora, compatible, pay, pricing, developer, matters, excels, microservices, maximum, thin, wrapper, ado, hybrid, writes, benefit, reads, hand, tuned, which, indexed, manageable, chunks, stream, datasets, everything, selecting, views, materialized, denormalized, reporting, exports, jobs, progress, synchronous, asasyncenumerable, sets, reports, joins, aggregations, inefficient, encapsulate, precise, plans, prevent, refactoring, usually, outweigh, executesqlraw, enforce, referential, integrity, cascading, deletes, designed, mode, slightly, accurate, depend, openconnection, behaviors, extension, capture, analyze, check, looking, similar, miniprofiler, insights, datadog, apm, diagnostics, slow, already, implements, clean, abstractions, dependencies, span, ability, stores, though, rare, abstracting, unnecessary, layers, obscure, power, refactor, concrete, reason, direct, enhanced, executions, gains, batch, meaningfully, previous, manager, reddit, overflow, issues, discussions, efcore, devblogs, blog, https, todoapiefcorebasic, todoapiefcoreadvanced, complete, examples, implementations, projects, release, notes, official, uis, consume, learned, continue, journey, requiring, mocking, getalltodos_returnsalltodos, useinmemorydatabase, databasename, testdatabase, getallasync, alternative, updatetodo_concurrentmodification_throwsconcurrencyexception, share, openasync, ensurecreatedasync, original, second, sharing, two, throwsasync, usage, getincompletetodos_returnsonlyincomplete, getincompletetodosasync, xunit, idisposable, createtodo_savessuccessfully, notnull, non, smooth, transitions, document, target, before, generation, isstaging, nvarchar, max, istemporal, historicaltodos, temporalasof, optimized, ismemoryoptimized, jsonb, totsvector, matches, totsquery, insensitive, comparison, ilike, limited, ideal, scale, off, commandtimeout, invalidoperationexception, unsupported, enabledetailederrors, host, username, postgres, password, pass, trusted_connection, trustservercertificate, supports, deploy, speed, dynamically, path, execute, stable, shapes, variable, stick, offs, volumes, index, clause, distributed, rarely, mostly, object, graphs, aggregates, parameters, concatenation, security, plan, parameterize, actual, log, executeupdateasync, addmonths, executedeleteasync, statement, savechangesinterceptor, savingchanges, dbcontexteventdata, changetracker, entries, deleted, interface, addinterceptors, soft, interceptors, reusable, firstordefault, gettodobyidasync, getoverduetodosasync, collections, cartesian, explosion, assplitquery, splits, left, causes, iteration, solving, tracks, detects, saves, usequerytrackingbehavior, querytrackingbehavior, notracking, identify, analysis, indexing, wraps, aggregate, coordinating, external, systems, enabled, reducing, extensions, http, enableretryonfailure, maxretrycount, maxretrydelay, errornumberstoadd, policy, waitandretryasync, pow, executeasync, policies, timestamp, byte, isrowversion, conflicts, conflict, was, another, please, refresh, again, token, optimistic, transfertodotonewcategoryasync, begintransactionasync, statistics, todocount, commitasync, rollbackasync, ensure, consistency, prevents, lost, users, modify, singleton, thread, holds, instance, lived, resolve, within, length, characters, less, detail, statuscode, 500, paged, totalpages, ceiling, double, paginated, endpoint, post, put, mapdelete, wire, dependency, providing, disposal, existence, checks, used, clauses, searchtodosasync, contains, group, todosbycategory, groupby, conditions, filteredtodos, todotitle, grouping, aggregation, dto, todosummaries, getpagedtodosasync, filter, incomplete, due, sortedtodos, thenby, find, totaltodos, sorting, composable, translate, mastering, helps, readable, cases, cause, audit, guidance, proxies, uselazyloadingproxies, mark, enables, accessed, firstasync, demand, activetags, level, theninclude, owner, filtered, additional, assignedat, assignedby, cascade, hasmany, implicit, has, ondelete, deletebehavior, setnull, understanding, crucial, treat, commit, databases, bundles, scripts, running, force, last, applied, migrationname, range, addtags, self, contained, part, runs, startup, anyasync, addrangeasync, createscope, getrequiredservice, approaches, initial, partial, createtable, annotation, autoincrement, maxlength, defaultvaluesql, primarykey, pk_todos, createindex, ix_todos_isdone, down, droptable, structure, track, evolve, safely, incrementally, noise, localized, zipcode, ownsone, 100, owned, builders, entitytypebuilder, applyconfiguration, extract, dbcontextoptions, base, primary, natively, represent, manages, done, annotations, logs, loglevel, aspnetcore, allowedhosts, webapplication, createbuilder, args, addcontrollers, addendpointsapiexplorer, addswaggergen, useswagger, useswaggerui, usehttpsredirection, useauthorization, mapcontrollers, webapi, should, show, higher, globally, tool, global, verify, installation, cli, supported, upgrading, preparing, native, aot, smoothly, integration, cold, mechanisms, easier, statements, improving, map, simpler, schemas, building, solid, foundation, makes, worth, adopting, contents, confidently, other, implement, boundaries, coverage, takes, zero, progressing, safer, evolving, toward, testability, learning, along, way, paths, confidence, lightweight, orm, fewer, expressiveness, benefits, intermediate, min, updated, july, 2025, hands, home, main, content,
Text of the page (random words):
026 consider upgrading for json heavy models high throughput apis or when preparing for native aot deployment most ef core 7 applications upgrade smoothly with minimal code changes setup project creation you need the net 8 sdk and ef core tools to build data driven applications ef core works with multiple database providers through nuget packages install net 8 sdk and ef tools download the sdk from dotnet microsoft com download and install the ef core cli tools terminal copy dotnet version should show 8 0 x or higher install ef core tools globally dotnet tool install global dotnet ef verify ef tools installation dotnet ef version create your project create web api project copy dotnet new webapi n todoapiefcore cd todoapiefcore dotnet run add ef core packages install ef core packages copy sqlite provider for local development dotnet add package microsoft entityframeworkcore sqlite design tools for migrations dotnet add package microsoft entityframeworkcore design optional for postgresql in production dotnet add package npgsql entityframeworkcore postgresql optional for sql server in production dotnet add package microsoft entityframeworkcore sqlserver configure dbcontext in program cs program cs dbcontext setup copy var builder webapplication createbuilder args configure dbcontext with sqlite builder services adddbcontext appdbcontext options options usesqlite builder configuration getconnectionstring defaultconnection builder services addcontrollers builder services addendpointsapiexplorer builder services addswaggergen var app builder build if app environment isdevelopment app useswagger app useswaggerui app usehttpsredirection app useauthorization app mapcontrollers app run add connection string appsettings json copy logging loglevel default information microsoft aspnetcore warning microsoft entityframeworkcore information allowedhosts connectionstrings defaultconnection data source todos db tip sensitive data logging use enablesensitivedatalogging only in development to see parameter values in sql logs run dotnet ef database update to apply migrations and create your database schema models dbcontext entity classes represent your domain model while dbcontext manages connections change tracking and queries configuration can be done through conventions data annotations or fluent api define your entity model todo cs entity model copy public class todo public int id get set public string title get set string empty public bool isdone get set public datetime duedate get set public list string tags get set new public datetime createdat get set public datetime updatedat get set create dbcontext appdbcontext cs copy using microsoft entityframeworkcore public class appdbcontext dbcontext public appdbcontext dbcontextoptions appdbcontext options base options public dbset todo todos set todo protected override void onmodelcreating modelbuilder modelbuilder modelbuilder entity todo entity primary key entity haskey t t id required fields entity property t t title isrequired hasmaxlength 200 indexes for common queries entity hasindex t t isdone entity hasindex t t duedate default value entity property t t createdat hasdefaultvaluesql datetime now store tags as json sqlite doesn t support json columns natively entity property t t tags hasconversion v string join v v v split stringsplitoptions removeemptyentries tolist fluent api configuration for complex configuration extract entity configuration into separate classes todoconfiguration cs copy using microsoft entityframeworkcore using microsoft entityframeworkcore metadata builders public class todoconfiguration ientitytypeconfiguration todo public void configure entitytypebuilder todo builder builder haskey t t id builder property t t title isrequired hasmaxlength 200 builder hasindex t t isdone builder hasindex t t duedate builder property t t createdat hasdefaultvaluesql datetime now builder property t t tags hasconversion v string join v v v split stringsplitoptions removeemptyentries tolist in dbcontext protected override void onmodelcreating modelbuilder modelbuilder modelbuilder applyconfiguration new todoconfiguration value objects with owned types complex types copy public class address public string street get set string empty public string city get set string empty public string zipcode get set string empty public class customer public int id get set public string name get set string empty public address shippingaddress get set new configuration modelbuilder entity customer ownsone c c shippingaddress address address property a a street hasmaxlength 200 address property a a city hasmaxlength 100 configuration best practices prefer ef core conventions for simple scenarios they reduce configuration noise use fluent api for indexes constraints and relationships keep advanced configuration localized in ientitytypeconfiguration classes for maintainability migrations seeding migrations track schema changes and evolve your database safely ef core generates migration code from your model changes applying them incrementally create your first migration terminal create migration copy generate migration from model changes dotnet ef migrations add initialcreate apply migration to database dotnet ef database update view migration sql without applying dotnet ef migrations script migration file structure generated migration copy public partial class initialcreate migration protected override void up migrationbuilder migrationbuilder migrationbuilder createtable name todos columns table new id table column int nullable false annotation sqlite autoincrement true title table column string maxlength 200 nullable false isdone table column bool nullable false duedate table column datetime nullable true tags table column string nullable false createdat table column datetime nullable false defaultvaluesql datetime now updatedat table column datetime nullable true constraints table table primarykey pk_todos x x id migrationbuilder createindex name ix_todos_isdone table todos column isdone protected override void down migrationbuilder migrationbuilder migrationbuilder droptable name todos seeding data seed initial data using hasdata in migrations or through a seeding service data seeding approaches copy approach 1 hasdata in configuration part of migrations protected override void onmodelcreating modelbuilder modelbuilder modelbuilder entity todo hasdata new todo id 1 title learn ef core isdone false createdat datetime utcnow new todo id 2 title build api isdone false createdat datetime utcnow approach 2 seeding service runs at app startup public class databaseseeder private readonly appdbcontext _context public databaseseeder appdbcontext context _context context public async task seedasync if await _context todos anyasync await _context todos addrangeasync new todo title learn ef core createdat datetime utcnow new todo title build api createdat datetime utcnow await _context savechangesasync register and run in program cs using var scope app services createscope var context scope serviceprovider getrequiredservice appdbcontext var seeder new databaseseeder context await seeder seedasync migration commands common migration commands copy list all migrations dotnet ef migrations list remove last migration if not applied dotnet ef migrations remove update to specific migration dotnet ef database update migrationname generate sql script for specific migration range dotnet ef migrations script initialcreate addtags create migration bundle for deployment dotnet ef migrations bundle self contained tip migration best practices treat migrations as code commit them to source control never use force on production databases test migrations on a staging environment first for deployment use migration bundles or sql scripts rather than running migrations from application code relationships navigation ef core models relationships between entities through navigation properties and foreign keys understanding loading strategies is crucial for query performance one to many relationship one to many example copy public class category public int id get set public string name get set string empty navigation property one category has many todos public list todo todos get set new public class todo public int id get set public string title get set string empty foreign key public int categoryid get set navigation property public category category get set configuration often not needed conventions work modelbuilder entity todo hasone t t category withmany c c todos hasforeignkey t t categoryid ondelete deletebehavior setnull many to many relationship many to many with implicit join copy public class todo public int id get set public string title get set string empty navigation property public list tag tags get set new public class tag public int id get set public string name get set string empty navigation property public list todo todos get set new ef core 5 creates join table automatically configuration only needed for custom join table or cascade rules modelbuilder entity todo hasmany t t tags withmany tag tag todos many to many with explicit join entity explicit join entity copy use explicit join when you need extra columns public class todotag public int todoid get set public todo todo get set null public int tagid get set public tag tag get set null additional columns public datetime assignedat get set public string assignedby get set string empty configuration modelbuilder entity todotag haskey tt new tt todoid tt tagid modelbuilder entity todotag hasone tt tt todo withmany hasforeignkey tt tt todoid modelbuilder entity todotag hasone tt tt tag withmany hasforeignkey tt tt tagid loading strategies eager loading explicit loading lazy loading eager loading with include copy load related data in the same query var todos await context todos include t t category include t t tags tolistasync multi level include var todos await context todos include t t category theninclude c c owner tolistasync filtered include ef core 5 var todos await context todos include t t tags where tag tag isactive tolistasync explicit loading copy load related data on demand var todo await context todos findasync id if todo null load category if needed await context entry todo reference t t category loadasync load collection await context entry todo collection t t tags loadasync query collection var activetags await context entry todo collection t t tags query where tag tag isactive tolistasync lazy loading optional copy install microsoft entityframeworkcore proxies enable in dbcontext protected override void onconfiguring dbcontextoptionsbuilder optionsbuilder optionsbuilder uselazyloadingproxies mark navigation properties as virtual public class todo public int id get set public string title get set string empty virtual enables lazy loading public virtual category category get set public virtual list tag tags get set new now navigation properties load automatically when accessed var todo await context todos firstasync var categoryname todo category name triggers db query loading strategy guidance use eager loading with include when you know you ll need related data one query is better than n 1 use explicit loading for conditional scenarios avoid lazy loading in most cases it can cause n 1 query problems and doesn t work with asnotracking use an explicit join entity when you need extra columns or audit fields in many to many relationships linq in practice linq provides type safe composable queries that translate to sql mastering linq patterns helps you write efficient readable data access code basic filtering and sorting common query patterns copy filter incomplete todos var incompletetodos await context todos where t t isdone tolistasync order by due date var sortedtodos await context todos orderby t t duedate thenby t t title tolistasync find by id var todo await context todos firstordefaultasync t t id id count var totaltodos await context todos countasync var completedcount await context todos countasync t t isdone pagination efficient pagination copy public record pagedresult t list t items int totalcount int page int pagesize public async task pagedresult todo getpagedtodosasync int page int pagesize var query context todos where t t isdone var totalcount await query countasync var items await query orderby t t duedate skip page 1 pagesize take pagesize tolistasync return new pagedresult todo items totalcount page pagesize projection to dtos select to dtos copy public record todosummarydto int id string title bool isdone datetime duedate project to dto early to reduce data transfer var todosummaries await context todos where t t isdone select t new todosummarydto t id t title t isdone t duedate tolistasync with navigation properties public record todowithcategorydto int id string title string categoryname var todoswithcategories await context todos select t new todowithcategorydto t id t title t category null t category name null tolistasync advanced queries grouping and aggregation copy group by category var todosbycategory await context todos groupby t t categoryid select g new categoryid g key count g count completedcount g count t t isdone tolistasync complex filtering with multiple conditions var filteredtodos await context todos where t t isdone t duedate hasvalue t duedate value datetime now adddays 7 t tags any tolistasync join queries var todoswithcategories await context todos join context categories todo todo categoryid category category id todo category new todotitle todo title categoryname category name tolistasync dynamic queries conditional filtering copy public async task list todo searchtodosasync string searchterm bool isdone int categoryid var query context todos asqueryable if string isnullorwhitespace searchterm query query where t t title contains searchterm if isdone hasvalue query query where t t isdone isdone value if categoryid hasvalue query query where t t categoryid categoryid value return await query orderby t t duedate tolistasync tip query performance prefer asnotracking for read only queries to avoid change tracking overhead project to dtos early with select to reduce data transfer use any instead of count 0 for existence checks always add indexes to columns used in where order by and join clauses integrating ef core with asp net core apis wire ef core into your api endpoints using dependency injection dbcontext is request scoped by default providing proper isolation and disposal basic crud endpoints program cs minimal api endpoints copy get todos app mapget todos async appdbcontext db var todos await db todos asnotracking orderby t t duedate tolistasync return results ok todos get todos id app mapget todos id async int id appdbcontext db var todo await db todos findasync id return todo is not null results ok todo results notfound post todos app mappost todos async createtodorequest request appdbcontext db var todo new todo title request title duedate request duedate createdat datetime utcnow db todos...
|