[C#] How to Exclude Specific Properties from the Database in Entity Framework Core

目次

Overview

When designing entities with Entity Framework Core (EF Core), you might want to prevent certain properties in a class from being created as columns in a database table. This guide explains how to use the [NotMapped] attribute from Data Annotations to exclude temporary calculation results or UI display flags from database management.

Specifications

  • Input: A property defined in an entity class.
  • Process: Apply the [NotMapped] attribute to the target property.
  • Output: The property is ignored during database operations such as SELECT, INSERT, and UPDATE.

Basic Usage

Use the System.ComponentModel.DataAnnotations.Schema namespace and apply the attribute to the property.

[NotMapped]
public string TemporaryMessage { get; set; }

Full Code Example

The following code is a complete console application example that uses the EF Core In-Memory database. You can see that even after saving data, the value of EstimatedProcessTime is not persisted and returns to its default value when reloaded.

Note: Requires the Microsoft.EntityFrameworkCore.InMemory package. dotnet add package Microsoft.EntityFrameworkCore.InMemory

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using Microsoft.EntityFrameworkCore;

namespace NotMappedSample
{
    // 1. Entity class definition
    public class ProductionOrder
    {
        [Key]
        public int OrderId { get; set; }

        public string ProductName { get; set; } = string.Empty;

        public int Quantity { get; set; }

        // This property will not be created in the database table.
        // It is used for temporary calculations or display within the application.
        [NotMapped]
        public TimeSpan EstimatedProcessTime { get; set; }
    }

    // 2. DbContext definition
    public class FactoryContext : DbContext
    {
        public DbSet<ProductionOrder> Orders { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            // Use in-memory database for testing
            optionsBuilder.UseInMemoryDatabase("FactoryDb");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // Saving data
            using (var context = new FactoryContext())
            {
                var newOrder = new ProductionOrder
                {
                    ProductName = "Widget-X",
                    Quantity = 100,
                    // Set the value in memory
                    EstimatedProcessTime = TimeSpan.FromHours(2.5) 
                };

                context.Orders.Add(newOrder);
                context.SaveChanges();

                Console.WriteLine($"[At Saving] ID: {newOrder.OrderId}, EstimatedProcessTime: {newOrder.EstimatedProcessTime}");
            }

            // Loading data
            using (var context = new FactoryContext())
            {
                var savedOrder = context.Orders.FirstOrDefault();

                if (savedOrder != null)
                {
                    Console.WriteLine("--- Reloading from Database ---");
                    Console.WriteLine($"[At Loading] ID: {savedOrder.OrderId}, Name: {savedOrder.ProductName}");
                    
                    // Because of the NotMapped attribute, it is not saved in the DB.
                    // It returns to the default value (TimeSpan.Zero).
                    Console.WriteLine($"[At Loading] EstimatedProcessTime: {savedOrder.EstimatedProcessTime}");
                }
            }
        }
    }
}

Execution Results Example

[At Saving] ID: 1, EstimatedProcessTime: 02:30:00
--- Reloading from Database ---
[At Loading] ID: 1, Name: Widget-X
[At Loading] EstimatedProcessTime: 00:00:00

Customization Points

  • Calculated Properties: Properties with only a getter (e.g., public int Total => Price * Count;) are often ignored automatically by EF Core. However, [NotMapped] is useful if a setter exists or if you want to explicitly exclude it.
  • UI State Flags: This is ideal for properties used in client-side applications like WPF or Blazor, such as row selection states (IsSelected) or expansion states (IsExpanded).

Important Notes

  • Not Supported in LINQ Queries: You cannot use properties marked with [NotMapped] in the Where clause of a LINQ to Entities query. This causes a runtime exception because the property cannot be converted to SQL. Always use columns that exist in the database for queries.
  • Data Loss: As explained, values are lost once the context is disposed and reloaded. Never use this for data that requires persistence.
  • Impact on Migrations: If you add this attribute to a property that already exists as a column in the database, running a migration will generate SQL to delete that column. Be careful as this will result in data loss.

Variations

Using Fluent API

If you want to keep your entity classes clean (POCO), you can configure this in the OnModelCreating method instead of using attributes.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<ProductionOrder>()
        .Ignore(p => p.EstimatedProcessTime);
}

Summary

Apply [NotMapped] to properties that you do not want to match with database table columns. This is suitable for temporary calculated values, UI state management, or temporary data for logging. Ensure you do not use these properties as search conditions in LINQ queries.

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次