【问题标题】:PostgreSQL: 42883: operator does not exist: information_schema.sql_identifier + unknownPostgreSQL:42883:运算符不存在:information_schema.sql_identifier + 未知
【发布时间】:2020-04-04 03:39:39
【问题描述】:

.NET Core 2.2 应用程序与 Npgsql EF Core 2.2.4、Npgsql Nodatime 2.2.4

我正在尝试批量更新记录,但 Entity Framework 抛出异常 42883: operator does not exist: information_schema.sql_identifier + unknown

如果我不使用 BulkUpdate 而是使用

_dbContext.UpdateRange(data)
_dbContext.SaveChanges();

那么一切都很好。但我想知道为什么它不适用于_dbContext.BulkUpdate(data)

以下是我们正在做的经过净化的版本:

public void BulkUpdate(List<AutoAction> data)
{
    try
    {
        _dbContext.BulkUpdate(data);
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
        throw;
    }
}

public class AutoAction
{
    public int Id { get; set; }
    public int SettingsId { get; set; }
    public Settings Setting { get; set; }
    public Type ActionType { get; set; }
    public LocalDate DateEffective { get; set; }
    public bool Processed { get; set; }
    public Instant CreatedDateUtc { get; set; }
    public Instant? ProcessedOnUtc { get; set; }
    public Status Status { get; set; }
}

DbContext.cs

public DbSet<AutoAction> AutoActions { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.ApplyConfiguration(new AutoActionConfiguration());
    base.OnModelCreating(modelBuilder);
}

AutoActionConfiguration.cs

public class AutoActionConfiguration : IEntityTypeConfiguration<AutoAction> 
{
    public void Configure(EntityTypeBuilder<AutoAction> builder)
    {
        builder.ToTable("AutoAction");
        builder.HasKey(x => x.Id);
        builder.Ignore(x => x.Setting);
        builder.Property(x => x.Id).ValueGeneratedOnAdd();
        builder.Property(a => a.Processed).HasColumnType("BOOLEAN");
        builder.Property(a => a.ProcessedOnUtc).HasColumnType("timestamp");
        builder.Property(a => a.CreatedDateUtc).HasColumnType("timestamp");
        builder.Property(a => a.DateEffective).HasColumnType("date");

        var actionTypeConverter = new EnumToNumberConverter<Type, int>();
        builder.Property(a => a.ActionType).HasConversion(actionTypeConverter).HasColumnName("ActionType");

        var statusTypeConverter = new EnumToNumberConverter<Status, int>();
        builder.Property(a => a.Status).HasConversion(statusTypeConverter).HasColumnName("Status");
    }
}

Startup.cs

services.AddDbContext<DbContext>((serviceProvider, options) =>
            {
                var factory = serviceProvider.GetRequiredService<IConnectionFactory>();

                var connection = factory.GetPostgresServerConnection();

                options.UseNpgsql(connection, optionsBuilder =>
                {
                    var coreOptionsBuilder = ((IRelationalDbContextOptionsBuilderInfrastructure)optionsBuilder).OptionsBuilder;

                    var extension = coreOptionsBuilder.Options.FindExtension<NpgsqlNodaTimeOptionsExtension>()
                                    ?? new NpgsqlNodaTimeOptionsExtension();

                    ((IDbContextOptionsBuilderInfrastructure)coreOptionsBuilder).AddOrUpdateExtension(extension);
                });
            });

异常

hint: No operator matches the given name and argument types. You might need to add explicit type casts.

stacktrace: at Npgsql.NpgsqlConnector.<>c__DisplayClass161_0.<<ReadMessage>g__ReadMessageLong|0>d.MoveNext()
End of stack trace from previous location where exception was thrown ---
   at Npgsql.NpgsqlConnector.<>c__DisplayClass161_0.<<ReadMessage>g__ReadMessageLong|0>d.MoveNext() in C:\projects\npgsql\src\Npgsql\NpgsqlConnector.cs:line 1032
End of stack trace from previous location where exception was thrown ---
   at Npgsql.NpgsqlDataReader.NextResult(Boolean async, Boolean isConsuming) in C:\projects\npgsql\src\Npgsql\NpgsqlDataReader.cs:line 446
   at Npgsql.NpgsqlDataReader.NextResult() in C:\projects\npgsql\src\Npgsql\NpgsqlDataReader.cs:line 332
   at Npgsql.NpgsqlCommand.ExecuteDbDataReader(CommandBehavior behavior, Boolean async, CancellationToken cancellationToken) in C:\projects\npgsql\src\Npgsql\NpgsqlCommand.cs:line 1218
   at Npgsql.NpgsqlCommand.ExecuteDbDataReader(CommandBehavior behavior) in C:\projects\npgsql\src\Npgsql\NpgsqlCommand.cs:line 1130
   at EFCore.BulkExtensions.TableInfo.CheckHasIdentity(DbContext context)
   at EFCore.BulkExtensions.SqlBulkOperation.Merge[T](DbContext context, IList`1 entities, TableInfo tableInfo, OperationType operationType, Action`1 progress)
   at EFCore.BulkExtensions.DbContextBulkExtensions.BulkUpdate[T](DbContext context, IList`1 entities, BulkConfig bulkConfig, Action`1 progress)

SQL: SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMNPROPERTY(object_id(TABLE_SCHEMA+'.'+TABLE_NAME), COLUMN_NAME, 'IsIdentity') = 1 and TABLE_NAME = 'autoaction' and TABLE_SCHEMA = 'dbo'
   42883: operator does not exist: information_schema.sql_identifier + unknown

不确定在哪里添加显式类型转换,因为它是作为异常提示提到的。

【问题讨论】:

  • BulkUpdate 方法从何而来?由于这不是 EF Core 的一部分,我假设它是一个第三方包,可能与 PostgreSQL 兼容,也可能不兼容。请包括完整的详细信息、版本等。

标签: c# npgsql asp.net-core-2.2 ef-core-2.2 bulkupdate


【解决方案1】:

我准备该错误的方式是尝试在表 rateautoaction 中查找具有 IDENTITY 属性的列并且不能。

似乎这是使用此功能的要求。

我不明白的另一部分是那里的 SQL 显示了正在调用的函数 COLUMNPROPERTY ——但这仅在 SQL Server 上。但是你说你使用的是 PostgreSQL。

您是否在 Postgre 中使用 SQL Server 库?那可不是个好主意。

【讨论】:

  • 来到你答案的第一部分,我将 configuration.cs 文件中的 IDENTITY 属性配置为builder.HasKey(x =&gt; x.Id); 但是由于某种原因,使用 BulkUpdate 还不够吗?在第二部分中,表位于 PostgreSQL 中,并且正确配置了 dbcontext 以使用该表。但是,在我的应用程序中,我们还使用了 Microsoft SQL Server 中的一些表,但它具有其上下文和配置。您认为这里的 SQL Server 配置有影响吗?
  • 该函数只对SQL Server有效。
猜你喜欢
  • 2020-04-14
  • 1970-01-01
  • 2017-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-05
  • 2011-06-12
  • 1970-01-01
相关资源
最近更新 更多