Not all database tables are created equal! Sometimes, you don’t need direct access to raw data—you need a refined, read-only version that makes querying easier. That’s where database views come in!
Database views are predefined queries stored in your database that let you access data without dealing with complex joins or filters every time. If you’re working with Entity Framework Core (EF Core) and need to bring those views into your app, you might be wondering:
- How do I map a view in EF Core?
- Can I generate code for it automatically?
- Do I need a primary key for views?
Good news! Reverse engineering database views in EF Core is simple—let’s dive in and explore how to do it.
Why Use Database Views in EF Core?
Database views are super useful for a variety of reasons:
Predefined Queries – Simplifies complex joins and aggregations.
Security & Data Access Control – Restrict access to sensitive data while still allowing queries.
Performance Boosts – Reduce redundant computations by letting the database handle data transformations.
Read-Only Access – Perfect for reporting and analytics dashboards.
Step 1: Set Up a Database View
Let’s assume we have a simple e-commerce database with Orders
, Customers
, and Products
. Instead of joining these tables every time we want to see order details, we can create a database view:
CREATE VIEW View_OrderSummary AS SELECT o.Id AS OrderId, c.Name AS CustomerName, p.Name AS ProductName, o.OrderDate, o.TotalAmount FROM Orders o JOIN Customers c ON o.CustomerId = c.Id JOIN Products p ON o.ProductId = p.Id;
This view pre-joins the data for us so we don’t have to write this query repeatedly.
Step 2: Reverse Engineer the View in EF Core
We need to bring this view into our EF Core model so we can query it easily. Instead of manually creating a model, let’s use EF Core’s Scaffold-DbContext
tool to reverse engineer the view.
Run the EF Core Reverse Engineering Command
Open your terminal and run:
dotnet ef dbcontext scaffold "Your_Connection_String" Microsoft.EntityFrameworkCore.SqlServer -o Models -t View_OrderSummary
What This Does:
- Connects to the database (
Your_Connection_String
) - Uses SQL Server provider (
Microsoft.EntityFrameworkCore.SqlServer
) - Scaffolds models into the
Models
folder - Includes the
View_OrderSummary
view
Step 3: Modify the Generated Model
After scaffolding, EF Core generates a class for the view inside your Models
folder:
public class ViewOrderSummary { public int OrderId { get; set; } public string CustomerName { get; set; } public string ProductName { get; set; } public DateTime OrderDate { get; set; } public decimal TotalAmount { get; set; } }
However, EF Core assumes everything is a table—so we need to tell it that this is a database view.
Modify DbContext
to Configure the View
Inside your AppDbContext.cs
, add this inside OnModelCreating
:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<ViewOrderSummary>() .HasNoKey() // Views don't have primary keys .ToView("View_OrderSummary"); // Map it to the actual view }
Why Use HasNoKey()
?
- Unlike tables, views don’t have a primary key.
- EF Core doesn’t track changes in views (since they’re read-only).
Step 4: Query the View in EF Core
Now, we can query the view just like any other DbSet:
var orderSummaries = await context.ViewOrderSummaries.ToListAsync(); foreach (var summary in orderSummaries) { Console.WriteLine($"{summary.CustomerName} bought {summary.ProductName} for ${summary.TotalAmount}"); }
That’s it! We can now fetch data from a database view in EF Core without dealing with complex joins every time!
When Should You Use Database Views in EF Core?
- For Reports & Dashboards – Views make it easier to precompute aggregations and retrieve read-only reports.
- When Using Complex Joins Frequently – If you find yourself writing the same joins repeatedly, use a view to simplify the query.
- For Security & Data Access Control – Restrict access to sensitive columns by exposing a limited view instead of the full table.
- Performance Optimization – Views allow the database to pre-optimize queries, reducing execution time.
Common Issues & How to Fix Them
EF Core Requires a Key for Views
- Fix it with
.HasNoKey()
inOnModelCreating()
.
Can’t Update Views
- Views are read-only in EF Core, so you can’t use
.Add()
,.Update()
, or.Remove()
. - If updates are needed, use INSTEAD OF triggers or a stored procedure.
Not Showing in Reverse Engineering?
- Some databases hide views from introspection. Try running:
dotnet ef dbcontext scaffold "Your_Connection_String" Microsoft.EntityFrameworkCore.SqlServer -o Models --force
Adding --force
ensures EF Core retrieves all objects from the database.
Wrap-Up: Simplify Queries with EF Core and Database Views
Database views are an awesome tool to simplify queries, improve performance, and make your data access more efficient. With EF Core’s reverse engineering, you can quickly generate models for views and start querying without writing complex joins every time.
Key Takeaways:
- Use database views for reports, security, and performance optimization.
- Reverse engineer views using
dotnet ef dbcontext scaffold
. - Tell EF Core that the entity has no primary key using
.HasNoKey()
. - Views are read-only—no inserts, updates, or deletes.
Next time you find yourself writing the same joins over and over, consider reverse engineering a database view instead!
Are you using views in EF Core? Let’s chat in the comments!
Would it be ok to add an index to a view so the example view “ViewOrderSummary” could be querieid where OrderId == ?
You can create an index on a view, and it helps. If the view is indexed then any queries that can be responded using the index only will never need to refer to the underlying tables. This can lead to an enormous improvement in performance. I am looking at only MSSQL for this rememb er so other database engines may be different. I do like Brent’s take https://www.brentozar.com/archive/2013/11/what-you-can-and-cant-do-with-indexed-views/