Entity Framework Extensions Input / Output / Ignore

In this article, we will discover how to choose which properties are used when inserting, updating, or deleting data through Entity Framework Extensions.

By default, all mapped properties are used — but this is not always the most efficient choice. Sometimes, you may want to update only specific properties, such as FirstName and LastName, or skip properties that should not be updated, such as CreatedDate.

Selecting only the properties you need can reduce the amount of data sent to the database and prevent accidental overwrites of important fields.

There are usually two ways to control this:

  • Choose which properties to map — all other properties will be ignored.
  • Choose which properties to ignore — all other properties will be included.

Both approaches can be combined. For example:

  • Map a few properties using ColumnInputExpression.
  • Ignore specific properties for the insert operation using IgnoreOnInsertExpression.

Prerequisites

Before continuing, we recommend reading the following articles first:


Quick Reference Table

Category Option Types Purpose Typical Usage
Column Input ColumnInputExpression, ColumnInputNames Choose which columns are sent to the database. Update only FirstName and LastName, skip audit fields.
Column Output ColumnOutputExpression, ColumnOutputNames Choose which columns are returned after the operation. Fetch only ModifiedDate updated by a trigger.
Column InputOutput ColumnInputOutputExpression, ColumnInputOutputNames Send and receive values for the same columns. Send a value for processing and get back the recalculated result.
OnMerge OnMergeInsertInputExpression, OnMergeUpdateInputExpression, OnMergeInsertInputNames, OnMergeUpdateInputNames Map input columns separately for insert and update during merge. Insert all columns, update only a few fields.
OnSynchronize OnSynchronizeInsertInputExpression, OnSynchronizeUpdateInputExpression, OnSynchronizeInsertInputNames, OnSynchronizeUpdateInputNames Map input columns separately for insert and update during synchronize. Insert all columns, update only modified ones.
Ignore (All) IgnoreColumnOutputExpression, IgnoreColumnOutputNames Skip specific columns entirely from output mapping. Avoid fetching large blobs unless needed.
Ignore on Insert IgnoreOnInsertExpression, IgnoreOnInsertNames Skip specific columns during insert. Ignore ModifiedDate because no modification yet.
Ignore on Update IgnoreOnUpdateExpression, IgnoreOnUpdateNames Skip specific columns during update. Ignore CreatedDate to preserve original value.
Ignore for Merge IgnoreOnMergeInsertExpression, IgnoreOnMergeUpdateExpression, IgnoreOnMergeInsertNames, IgnoreOnMergeUpdateNames Skip specific columns separately for insert/update in merge. Insert: skip ModifiedDate; Update: skip CreatedDate.
Ignore for Synchronize IgnoreOnSynchronizeInsertExpression, IgnoreOnSynchronizeUpdateExpression, IgnoreOnSynchronizeInsertNames, IgnoreOnSynchronizeUpdateNames Skip specific columns separately for insert/update in synchronize. Insert: skip ModifiedDate; Update: skip CreatedDate.

Column Input

The ColumnInputExpression and ColumnInputNames options in Entity Framework Extensions let you specify which properties will be inserted or updated — all other properties will be ignored.

These options apply to the following bulk operations:

Restricting the Input columns to only what’s necessary reduces unnecessary database writes and helps prevent accidental changes to other fields.

For example, you might update only FirstName and LastName without touching audit fields such as CreatedDate.

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// ColumnInputExpression: Select properties to insert or update
context.BulkUpdate(customers, options => { 
    options.ColumnInputExpression = x => new { x.FirstName, x.LastName };
});

// ColumnInputNames: Select properties by name
context.BulkUpdate(customers, options => {
    options.ColumnInputNames = new List<string>() { nameof(Customer.FirstName), nameof(Customer.LastName) };
});

Column Output

The ColumnOutputExpression and ColumnOutputNames options in Entity Framework Extensions let you choose which columns will be returned after an insert or update.

The values from the database are automatically mapped back to your entities.

These options apply to the following bulk operations:

Restricting the Output columns avoids fetching unused data, which helps improve performance in high-throughput scenarios.

For example, if you have a trigger that automatically updates the ModifiedDate column, you can return only that column so the new value is reflected in your entities without reloading the entire row.

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// ColumnOutputExpression: Return only the updated ModifiedDate
context.BulkUpdate(customers, options => { 
    options.ColumnInputExpression = x => new { x.FirstName, x.LastName };
    options.ColumnOutputExpression = x => new { x.ModifiedDate };
});

// ColumnOutputNames: Return only the updated ModifiedDate by name
context.BulkUpdate(customers, options => {
    options.ColumnInputExpression = x => new { x.FirstName, x.LastName };
    options.ColumnOutputNames = new List<string>() { nameof(Customer.ModifiedDate) };
});

Column InputOutput

The ColumnInputOutputExpression and ColumnInputOutputNames options in Entity Framework Extensions combine the functionality of both Column Input and Column Output. They work in both directions:

  • Input: The value is taken from the entity and sent to the database for the insert, update, or merge.
  • Output: The updated value from the database is mapped back to the entity after the operation.

These options apply to the following bulk operations:

Restricting InputOutput columns avoids sending and fetching unused data, which improves performance and prevents accidental overwrites.

This mapping is especially useful if you have database-side logic (such as triggers) that modifies values during the operation.

For example, you might send a value to the database for processing, and then receive back a normalized or recalculated version of it.

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// ColumnInputOutputExpression: return ModifiedDate
context.BulkMerge(customers, options => { 
    options.ColumnInputExpression = x => new { x.FirstName, x.LastName };
    options.ColumnInputOutputExpression = x => new { x.ModifiedDate };
});

// ColumnInputOutputNames: return ModifiedDate by name
context.BulkMerge(customers, options => {
    options.ColumnInputNames = new List<string>() { nameof(Customer.FirstName), nameof(Customer.LastName) };
    options.ColumnInputOutputNames = new List<string>() { nameof(Customer.ModifiedDate) };
});

OnMerge / OnSynchronize

The BulkMerge and BulkSynchronize methods handle both insert and update behaviors.

Note: Depending on the database provider, this can run as a single upsert-style statement or as multiple statements/batches.

  • Some providers support a true single-statement upsert.
  • Others emulate the same result using a sequence of insert/update steps.

Sometimes, you may want to map columns for only one of these actions — for example, insert all columns but update only a few. This helps avoid sending unused data, improves performance, and reduces the risk of overwriting fields that should not change.

You can control this per action with the following options:

  • BulkMerge

    • OnMergeInsertInputExpression
    • OnMergeUpdateInputExpression
    • OnMergeInsertInputNames
    • OnMergeUpdateInputNames
  • BulkSynchronize

    • OnSynchronizeInsertInputExpression
    • OnSynchronizeUpdateInputExpression
    • OnSynchronizeInsertInputNames
    • OnSynchronizeUpdateInputNames

You can also mix these with ColumnInputExpression or ColumnInputNames.

For example, define a default set of input columns, then further restrict the update part using OnMergeUpdateInputExpression.

Bulk Merge example

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// Expressions: Insert CreatedDate, Update ModifiedDate
context.BulkMerge(customers, options => { 
    options.ColumnInputExpression = x => new { x.FirstName, x.LastName };

    // Per-action input overrides
    options.OnMergeInsertInputExpression = x => new { x.CreatedDate };
    options.OnMergeUpdateInputExpression = x => new { x.ModifiedDate };
});

// Names: Insert CreatedDate, Update ModifiedDate
context.BulkMerge(customers, options => {
    options.ColumnInputNames = new List<string> { nameof(Customer.FirstName), nameof(Customer.LastName) };

    // Per-action input overrides
    options.OnMergeInsertInputNames = new List<string> { nameof(Customer.CreatedDate) };
    options.OnMergeUpdateInputNames = new List<string> { nameof(Customer.ModifiedDate) };
});

Bulk Synchronize example

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// Expressions: Insert CreatedDate, Update ModifiedDate
context.BulkSynchronize(customers, options => { 
    options.ColumnInputExpression = x => new { x.FirstName, x.LastName };

    options.OnSynchronizeInsertInputExpression = x => new { x.CreatedDate };
    options.OnSynchronizeUpdateInputExpression = x => new { x.ModifiedDate };
});

// Names: Insert CreatedDate, Update ModifiedDate
context.BulkSynchronize(customers, options => {
    options.ColumnInputNames = new List<string> { nameof(Customer.FirstName), nameof(Customer.LastName) };

    options.OnSynchronizeInsertInputNames = new List<string> { nameof(Customer.CreatedDate) };
    options.OnSynchronizeUpdateInputNames = new List<string> { nameof(Customer.ModifiedDate) };
});

Bulk Synchronize example

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// Expressions: Insert CreatedDate, Update ModifiedDate
context.BulkSynchronize(customers, options => { 
    options.ColumnInputExpression = x => new { x.FirstName, x.LastName };

    options.OnSynchronizeInsertInputExpression = x => new { x.CreatedDate };
    options.OnSynchronizeUpdateInputExpression = x => new { x.ModifiedDate };
});

// Names: Insert CreatedDate, Update ModifiedDate
context.BulkSynchronize(customers, options => {
    options.ColumnInputNames = new List<string> { nameof(Customer.FirstName), nameof(Customer.LastName) };

    options.OnSynchronizeInsertInputNames = new List<string> { nameof(Customer.CreatedDate) };
    options.OnSynchronizeUpdateInputNames = new List<string> { nameof(Customer.ModifiedDate) };
});

Ignore

Instead of selecting which columns to include, you can ignore specific columns.

Ignoring columns helps you avoid sending or returning data you don’t need, which improves performance and reduces the risk of overwriting fields that should remain unchanged.

A common best practice:

  • On insert → Ignore ModifiedDate because there’s no modification yet.
  • On update → Ignore CreatedDate to preserve the original creation date.

These options are available:

  • All

    • IgnoreColumnOutputExpression
    • IgnoreColumnOutputNames
  • Bulk Insert

    • IgnoreOnInsertExpression
    • IgnoreOnInsertNames
  • Bulk Update

    • IgnoreOnUpdateExpression
    • IgnoreOnUpdateNames
  • Bulk Merge

    • IgnoreOnMergeInsertExpression
    • IgnoreOnMergeUpdateExpression
    • IgnoreOnMergeInsertNames
    • IgnoreOnMergeUpdateNames
  • Bulk Synchronize

    • IgnoreOnSynchronizeInsertExpression
    • IgnoreOnSynchronizeUpdateExpression
    • IgnoreOnSynchronizeInsertNames
    • IgnoreOnSynchronizeUpdateNames

Ignore Output Columns (example)

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// Expression: do not fetch LargeImage after the operation (saves bandwidth)
context.BulkUpdate(customers, options =>
{
    options.IgnoreColumnOutputExpression = x => new { x.LargeImage };
});

// Names: do not fetch LargeImage after the operation
context.BulkUpdate(customers, options =>
{
    options.IgnoreColumnOutputNames = new List<string> { nameof(Customer.LargeImage) };
});

Ignore on Insert (example)

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// Expression: do not write ModifiedDate during insert
context.BulkInsert(customers, options =>
{
    options.IgnoreOnInsertExpression = x => new { x.ModifiedDate };
});

// Names: do not write ModifiedDate during insert
context.BulkInsert(customers, options =>
{
    options.IgnoreOnInsertNames = new List<string> { nameof(Customer.ModifiedDate) };
});

Ignore on Update (example)

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// Expression: do not update CreatedDate during update (preserve original creation date)
context.BulkUpdate(customers, options =>
{
    options.IgnoreOnUpdateExpression = x => new { x.CreatedDate };
});

// Names: do not update CreatedDate during update (preserve original creation date)
context.BulkUpdate(customers, options =>
{
    options.IgnoreOnUpdateNames = new List<string> { nameof(Customer.CreatedDate) };
});

Ignore for Merge (example)

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// Expression: ignore specific columns per action in BulkMerge
context.BulkMerge(customers, options =>
{
    // On insert, do not write ModifiedDate
    options.IgnoreOnMergeInsertExpression = x => new { x.ModifiedDate };

    // On update, do not touch CreatedDate (preserve original creation date)
    options.IgnoreOnMergeUpdateExpression = x => new { x.CreatedDate };
});

// Names: ignore specific columns per action in BulkMerge
context.BulkMerge(customers, options =>
{
    // On insert, do not write ModifiedDate
    options.IgnoreOnMergeInsertNames = new List<string> { nameof(Customer.ModifiedDate) };

    // On update, do not touch CreatedDate (preserve original creation date)
    options.IgnoreOnMergeUpdateNames = new List<string> { nameof(Customer.CreatedDate) };
});

Ignore for Synchronize (example)

// @nuget: Z.EntityFramework.Extensions.EFCore
using Z.EntityFramework.Extensions;

// Expression: ignore specific columns per action in BulkSynchronize
context.BulkSynchronize(customers, options =>
{
    // On insert, do not write ModifiedDate
    options.IgnoreOnSynchronizeInsertExpression = x => new { x.ModifiedDate };

    // On update, do not touch CreatedDate (preserve original creation date)
    options.IgnoreOnSynchronizeUpdateExpression = x => new { x.CreatedDate };
});

// Names: ignore specific columns per action in BulkSynchronize
context.BulkSynchronize(customers, options =>
{
    // On insert, do not write ModifiedDate
    options.IgnoreOnSynchronizeInsertNames = new List<string> { nameof(Customer.ModifiedDate) };

    // On update, do not touch CreatedDate (preserve original creation date)
    options.IgnoreOnSynchronizeUpdateNames = new List<string> { nameof(Customer.CreatedDate) };
});

Conclusion

Mastering the Input, Output, and Ignore column options in Entity Framework Extensions gives you fine-grained control over how data is sent to and retrieved from your database. By mapping only the properties you need—or ignoring those you don’t—you can:

  • Improve performance by reducing the amount of data processed.
  • Protect critical fields like CreatedDate and ModifiedDate from accidental changes.
  • Work efficiently with triggers and computed columns without unnecessary round-trips or overwrites.

Whether you’re inserting, updating, merging, or synchronizing data, these options let you adapt bulk operations to your exact needs while keeping your database clean, fast, and reliable. Start with small adjustments, test your mappings, and you’ll quickly see the benefits in both speed and data integrity.


Last updated: 2025-08-13
Author: