Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BulkInsertOrUpdateAsync fails for Postgres when unique index required #1638

Open
tejssidhu opened this issue Dec 14, 2024 · 0 comments
Open

Comments

@tejssidhu
Copy link

tejssidhu commented Dec 14, 2024

First of thank you for all the great work you guys do on this library.

So the issue I've experienced is using the BulkInsertOrUpdateAsync extension method and supplying update properties in the BulkConfig. When executed the action fails with the below error:

Exception data:
    Severity: ERROR
    SqlState: 42704
    MessageText: index "<indexName>" does not exist
    File: tablecmds.c
    Line: 1299
    Routine: DropErrorMsgNonExistent

I've created the below small program that replicates the issue:

using EFCore.BulkExtensions;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;

namespace EFBulkExtensionsPostgresIssue
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();

            var connectionString = Environment.GetEnvironmentVariable("DB_CONNECTION_STRING");
            optionsBuilder
                .UseNpgsql(connectionString);
            using var context = new BloggingContext(optionsBuilder.Options);

            var canConnect = await context.Database.CanConnectAsync();

            if (!canConnect)
            {
                Console.WriteLine("Cannot connect to database");
                return;
            }

            var items = new List<BlogAggregation>();
            Random rnd = new();

            for (var i = 0; i < 20; i++)
            {
                items.Add(new BlogAggregation
                {
                    Id = Guid.NewGuid(),
                    AggregationTypeId = 1,
                    CreatedAt = DateTime.UtcNow,
                    Value = rnd.Next(),
                    AggregationDate = DateTime.UtcNow.AddDays(i * -1)
                });
            }

            var bulkConfig = new BulkConfig
            {
                UpdateByProperties = [nameof(BlogAggregation.AggregationTypeId), nameof(BlogAggregation.AggregationDate)],
                PropertiesToIncludeOnUpdate = [nameof(BlogAggregation.Value), nameof(BlogAggregation.CreatedAt)]
            };

            await context.BulkInsertOrUpdateAsync(items, bulkConfig);
        }
    }

    public class BlogAggregation
    {
        [Key]
        public Guid Id { get; init; }
        public int AggregationTypeId { get; init; }
        public int Value { get; init; }
        public DateTime CreatedAt { get; init; }
        public DateTime AggregationDate { get; init; }
    }

    public class BloggingContext : DbContext
    {
        public DbSet<BlogAggregation> BlogAggregations { get; set; } = null!;

        public BloggingContext(DbContextOptions<BloggingContext> options) : base(options)
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.HasDefaultSchema("MySchema");
        }
    }
}

Using this I've diagnosed the issue and the two below are contributing:

  • index name lengths are limited to 64 chars in Postgres
  • the schema name is missing when the index is attempted to be deleted

I've also got a solution for this and would love to raise a PR but sharing here first as per the contributing guidelines.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant