aspnetboilerplate/aspnetboilerplate · error · ArgumentException

SequenceIdentity generator cannot be used with multi-column…

Error message

SequenceIdentity generator cannot be used with multi-column keys

What it means

This ArgumentException is thrown by DapperImplementor when an entity mapped with the DapperExtensions fluent mapper has more than one property marked as KeyType.SequenceIdentity. SequenceIdentity keys rely on a database sequence to generate a single identity value, so the library only supports exactly one such key per entity and refuses to build insert parameters otherwise.

Solutions

  1. Inspect the entity's ClassMapper mapping and keep only ONE property mapped with KeyType.SequenceIdentity
  2. Change the additional key properties to KeyType.Assigned or mark them Ignored if they are not real keys
  3. If a true composite key is needed, use KeyType.Assigned for all key columns instead of SequenceIdentity

Example fix

// before
Map(x => x.Id).Key(KeyType.SequenceIdentity);
Map(x => x.RowId).Key(KeyType.SequenceIdentity);
// after
Map(x => x.Id).Key(KeyType.SequenceIdentity);
Map(x => x.RowId).Key(KeyType.Assigned);
Defensive patterns

Strategy: validation

Validate before calling

var seqKeys = mapper.Properties.Count(p => p.KeyType == KeyType.SequenceIdentity);
if (seqKeys > 1) throw new InvalidOperationException("Entity must have at most one SequenceIdentity key");

Try / catch

try { DapperExtensions.Insert(connection, entity); }
catch (ArgumentException ex) when (ex.Message.Contains("SequenceIdentity"))
{
    // fix mapping or fall back to Assigned keys
}

Prevention

When it happens

Trigger: Calling GetDynamicParameters (or any insert path that reaches it, e.g. DapperExtensions.Insert) on a ClassMapper whose Properties contain two or more properties with KeyType == KeyType.SequenceIdentity (Key SequenceIdentity(...)).

Common situations: Copy-pasting fluent mapping lines so a composite-key entity ends up with two SequenceIdentity entries; refactoring a Guid key to a sequence key on one property while leaving the old mapping; bulk-generating mappings from templates.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of aspnetboilerplate/aspnetboilerplate@2323c13a15 (2026-09-08). Data as JSON: /api/errors/4e963822bffb4af0. Report an issue: GitHub.

Appendix: source

Thrown at src/Abp.Dapper/Dapper-Extensions/DapperImplementor.cs:559

            var dynamicParameters = new DynamicParameters();

            foreach (var prop in entity.GetType().GetProperties(BindingFlags.GetProperty | BindingFlags.GetField | BindingFlags.Instance | BindingFlags.Public)
                .Where(p => !keyColumns.Any(k => k.Name.Equals(p.Name)) && !foreignKeys.Contains(p) && !ignoredColumns.Contains(p)
                ))
                dynamicParameters = AddParameter(entity, dynamicParameters, new MemberMap(prop), useColumnAlias);

            return dynamicParameters;
        }

        public DynamicParameters GetDynamicParameters<T>(IClassMapper classMap, T entity, bool useColumnAlias = false)
        {
            var sequenceIdentityColumn = classMap.Properties.Where(p => p.KeyType == KeyType.SequenceIdentity)?.ToList();
            var foreignKeys = classMap.Properties.Where(p => p.KeyType == KeyType.ForeignKey).Select(p => p.MemberInfo).ToList();
            var ignored = classMap.Properties.Where(x => x.Ignored).Select(p => p.MemberInfo).ToList();

            if (sequenceIdentityColumn?.Count > 1)
                throw new ArgumentException("SequenceIdentity generator cannot be used with multi-column keys");

            return GetDynamicParameters(entity, classMap, sequenceIdentityColumn, foreignKeys, ignored, useColumnAlias);
        }

        public DynamicParameters GetDynamicParameters<T>(T entity, DynamicParameters dynamicParameters, IMemberMap keyColumn, bool useColumnAlias = false)
        {
            dynamicParameters ??= new DynamicParameters();
            foreach (var prop in entity.GetType().GetProperties(BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public)
                .Where(p => p.Name != keyColumn.Name))
                AddParameter(entity, dynamicParameters, new MemberMap(prop), useColumnAlias);

            return dynamicParameters;
        }

        /// <summary>
        /// Return property liste from (anonymous) type
        /// </summary>
        /// <typeparam name="T"></typeparam>

View on GitHub (pinned to 2323c13a15)