C# tutorials > Language Integrated Query (LINQ) > LINQ to Entities (Entity Framework Core) > What are shadow properties in EF Core?

What are shadow properties in EF Core?

Shadow properties in Entity Framework Core (EF Core) are properties that are not explicitly defined in your entity classes but are part of the database schema and managed by EF Core. These properties exist in the database table but are not exposed as CLR properties in your C# entity classes.

Shadow properties are typically used to store metadata or information that's not directly related to the core business logic represented by your entities. Common examples include tracking creation or modification timestamps or implementing soft deletes.

Introduction to Shadow Properties

EF Core allows you to define properties in your database schema that aren't directly mapped to properties in your entity classes. These are known as shadow properties. They are useful for storing information that the application doesn't need to directly interact with, but is important for data management or auditing.

For instance, you might have 'CreatedOn' and 'ModifiedOn' columns in your database tables to track when a record was created or last updated. If these details aren't core to your application's business logic, you can manage them as shadow properties.

Defining Shadow Properties

To define a shadow property, you use the OnModelCreating method in your DbContext class. This is where you configure the database schema.

In the example above, we define a shadow property named LastUpdated of type DateTime for the Blog entity. Notice that there's no LastUpdated property in the Blog class itself.

using Microsoft.EntityFrameworkCore;

public class BloggingContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Property<DateTime>("LastUpdated");
    }
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

Accessing Shadow Properties

To access shadow properties, you use the DbContext.Entry method to get an EntityEntry for the entity. Then, you use the Property method to access the shadow property by its name.

In the example above, we first retrieve a Blog entity. Then, we set the value of the LastUpdated shadow property to the current date and time. Finally, we read the value of the LastUpdated property and print it to the console.

using Microsoft.EntityFrameworkCore;

using (var context = new BloggingContext())
{
    var blog = context.Blogs.FirstOrDefault();

    // Setting the shadow property
    context.Entry(blog).Property("LastUpdated").CurrentValue = DateTime.Now;
    context.SaveChanges();

    // Reading the shadow property
    var lastUpdated = context.Entry(blog).Property("LastUpdated").CurrentValue;
    Console.WriteLine($"Last Updated: {lastUpdated}");
}

Concepts Behind the Snippet

  • EntityEntry: Represents the metadata and change tracking information for an entity instance that is being managed by an EF Core context.
  • Property(string propertyName): Returns an object that can be used to access the value of the property.
  • CurrentValue: Gets or sets the current value of the property.

Real-Life Use Case Section

A common use case is implementing soft deletes. Instead of physically deleting a record from the database, you set a flag (e.g., IsDeleted) to indicate that the record is no longer active. This allows you to retain historical data while logically removing it from the application.

Shadow properties can be used to store the date and time when a record was soft-deleted, or the user who performed the soft delete.

Best Practices

  • Use shadow properties when the data doesn't need to be directly accessed by the application's business logic.
  • Document shadow properties in your database schema to make it clear what they represent.
  • Consider using conventions or interceptors to automatically manage shadow properties like creation and modification timestamps.

Interview Tip

When discussing shadow properties in an interview, emphasize their role in separating concerns and managing metadata without cluttering your entity classes. Also, mention common use cases like audit trails, soft deletes, and concurrency tokens.

When to use them

Use shadow properties when:

  • You need to store metadata that is not directly related to your entity's core business logic.
  • You want to avoid adding extra properties to your entity classes that would clutter them and make them less readable.
  • You need to implement features like auditing, soft deletes, or concurrency control.

Memory footprint

Shadow properties can slightly increase the memory footprint of your application, as EF Core needs to track them. However, the impact is generally small, especially if you're only using a few shadow properties per entity.

Alternatives

Alternatives to shadow properties include:

  • Adding explicit properties to your entity classes. This makes the data directly accessible but can clutter your entities.
  • Using a separate audit table to store metadata. This keeps your entity classes clean but requires more complex querying.
  • Using database triggers to automatically manage metadata. This moves the logic to the database layer but can make debugging more difficult.

Pros

  • Keeps entity classes clean and focused on business logic.
  • Allows you to store metadata without cluttering your entities.
  • Provides a convenient way to implement features like auditing and soft deletes.

Cons

  • Shadow properties are not directly accessible through entity properties.
  • Requires using DbContext.Entry to access and manipulate them.
  • Can make queries slightly more complex.

FAQ

  • Are shadow properties included in the migration?

    Yes, shadow properties are included in the migrations generated by EF Core. The migration will create the corresponding columns in the database table.
  • Can I use shadow properties with existing database columns?

    Yes, you can map shadow properties to existing database columns. EF Core will automatically manage the data in those columns.
  • How do I configure the data type of a shadow property?

    You can specify the data type of a shadow property using the HasColumnType method in the OnModelCreating method. For example: modelBuilder.Entity().Property("LastUpdated").HasColumnType("datetime2");