FlexLabs.Upsert icon indicating copy to clipboard operation
FlexLabs.Upsert copied to clipboard

Upsert on conflict - Alias instead of exclude

Open Inexad opened this issue 2 years ago • 3 comments

I currently have a problem with Upsert not updating my entries in database.

 await _context.Articles.UpsertRange(articles)
                .On(x => x.Id)
                .WhenMatched(x => new Article()
                {
                    AccessId = x.AccessId
                })
                .AllowIdentityMatch()
                .RunAsync(cancellationToken);

Above generates following:

INSERT INTO "Articles" AS "T" ("Id", "AccessId") 
VALUES ('12345', '0') 
ON CONFLICT ("Id") DO UPDATE SET "AccessId" =  "T"."AccessId"

That query will run without any errors but the AccessId in database won't be updated.

If i instead manually change the SQL to:

INSERT INTO "Articles" AS "T" ("Id", "AccessId") 
VALUES ('12345', '0') 
ON CONFLICT ("Id") DO UPDATE SET "AccessId" =  excluded."AccessId"

It works as intended.

Anyone have any idea what could be the problem here? I run .net 7, latest upsert package, postgresql 14.

Inexad avatar Jan 18 '23 13:01 Inexad

When i remove the .WhenMatched() it seems to work? Then it produces the following SQL:

INSERT INTO "Articles" AS "T" ("Id", "AccessId") 
VALUES ('12345', '0') 
ON CONFLICT ("Id") DO UPDATE SET "AccessId" =  excluded."AccessId"

Any ideas why this is?

Inexad avatar Jan 18 '23 14:01 Inexad

Anyone?

Inexad avatar Feb 14 '23 09:02 Inexad

It seems that you should use another version of method. see..

        /// <summary>
        /// Specifies which columns should be updated when a matched entity is found.
        /// The second type parameter points to the entity that was originally passed to be inserted
        /// </summary>
        /// <param name="updater">The expression that returns a new instance of TEntity, with the columns that have to be updated being initialised with new values</param>
        /// <returns>The current instance of the UpsertCommandBuilder</returns>
        public UpsertCommandBuilder<TEntity> WhenMatched(Expression<Func<TEntity, TEntity, TEntity>> updater)
        {

Try this

await _context.Articles.UpsertRange(articles)
                .On(x => x.Id)
                .WhenMatched((_, x) => new Article()
                {
                    AccessId = x.AccessId
                })
                .AllowIdentityMatch()
                .RunAsync(cancellationToken);

xamele0n avatar Mar 09 '23 15:03 xamele0n