EF Core集成Npgsql时List<NpgsqlRange<LocalDateTime>>字段无法映射如何解决
使用EF Core对接PostgreSQL时,引入了如下NuGet包:
- Npgsql.EntityFrameworkCore.PostgreSQL 5.0.2
- Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime 5.0.2
实体类定义如下:
using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using Nest; namespace Vepo.Domain { [ElasticsearchType(RelationName = "eventitem", IdProperty = "Id")] public class EventItem : VeganItem<EventItemEstablishment> { [MaxLength(10)] public List<NpgsqlRange<LocalDateTime>> Dates { get; set; } } }
启动程序后抛出如下异常:
InvalidOperationException: The property ‘EventItem.Dates’ could not be mapped, because it is of type
List<NpgsqlRange<LocalDateTime>>which is not a supported primitive type or a valid entity type. Either explicitly map this property, or ignore it using the ‘[NotMapped]’ attribute or by using ‘EntityTypeBuilder.Ignore’ in ‘OnModelCreating’.
此前已经验证单独的LocalDateTime类型可以通过值转换器完成映射:
base.OnModelCreating(modelBuilder); var localDateConverter = new ValueConverter<LocalDate, DateTime>(v => v.ToDateTimeUnspecified(), v => LocalDate.FromDateTime(v)); modelBuilder.Entity<Event>() .Property(e => e.Date) .HasConversion(localDateConverter);
但该方案不适用List<NpgsqlRange<LocalDateTime>>类型,且前端传入后端的参数格式为[{DateTime startDate, DateTime endDate}],无法通过自定义值转换器适配。
问题出在NodaTime的注册方式错误,原有Startup.cs配置如下:
public void ConfigureServices(IServiceCollection services) { services .AddDbContext<VepoContext>(opt => { opt .UseNpgsql( Configuration .GetConnectionString("DefaultConnection")) .EnableSensitiveDataLogging() .EnableDetailedErrors() .LogTo(Console.WriteLine); }); NpgsqlConnection.GlobalTypeMapper.UseNodaTime(); }
只需将UseNodaTime()的调用挪到UseNpgsql的配置委托中即可,修改后的配置如下:
public void ConfigureServices(IServiceCollection services) { services .AddDbContext<VepoContext>(opt => { opt .UseNpgsql( Configuration .GetConnectionString("DefaultConnection"), o => o.UseNodaTime() ) .EnableSensitiveDataLogging() .EnableDetailedErrors() .LogTo(Console.WriteLine); }); }
修改后无需额外自定义值转换器,EF Core即可自动完成List<NpgsqlRange<LocalDateTime>>类型到PostgreSQL数组+范围类型的映射,也可正常适配前端传入的时间范围参数格式。
内容的提问来源于stack exchange,提问作者BeniaminoBaggins

