EF Core NodaTime 字段 - 无法映射

EF Core NodaTime field - could not be mapped

我在 <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="5.0.2" />

中使用 EF Core

我刚刚向我的实体添加了一个 NodaTime.LocalDate 字段,该字段使用名为 NodaTime 的包:

<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime" Version="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’.

所以 Ef Core 无法映射 List

这是一个演示,演示如何使用值转换器让 EF Core 映射 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);

但这对我不起作用,因为我的领域不是LocalDateTime,而是List<NpgsqlRange<LocalDateTime>>

我正在努力正确创建值转换器。任何帮助表示赞赏。

仅供参考我的前端正在向后端发送自定义对象列表:[{DateTime startDate, DateTime endDate}]

重要提示: Shay Rojansky 的版本对我有用,我需要更改我的 Startup.cs 代码:

public void ConfigureServices(IServiceCollection services)
{
    services
    .AddDbContext<VepoContext>(opt => {
        opt
        .UseNpgsql(
            Configuration
            .GetConnectionString("DefaultConnection"))
            .EnableSensitiveDataLogging()
            .EnableDetailedErrors()
            .LogTo(Console.WriteLine);
    });
    
    NpgsqlConnection.GlobalTypeMapper.UseNodaTime();

为此(基本上是他的 - 但我的初始化代码使用的是 ConfigureServices,而不是 OnConfiguring 所以我想我会 post 他的解决方案 ConfigureServices 语法这里是为代码已经在使用 ConfigureServices:

的人准备的
    services
    .AddDbContext<VepoContext>(opt => {
        opt
        .UseNpgsql(
            Configuration
            .GetConnectionString("DefaultConnection"), 
                o => o.UseNodaTime()
            )
            .EnableSensitiveDataLogging()
            .EnableDetailedErrors()
            .LogTo(Console.WriteLine);
    });

以上使用 5.0.10 对我有效,没有值转换器:

await using var ctx = new BlogContext();
await ctx.Database.EnsureDeletedAsync();
await ctx.Database.EnsureCreatedAsync();

public class BlogContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        => optionsBuilder
            .UseNpgsql(@"Host=localhost;Username=test;Password=test", o => o.UseNodaTime())
            .LogTo(Console.WriteLine, LogLevel.Information)
            .EnableSensitiveDataLogging();

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
    }
}

public class Blog
{
    public int Id { get; set; }
    public List<NpgsqlRange<LocalDateTime>> Dates { get; set; }
}

创建了以下 table:

CREATE TABLE "Blogs" (
    "Id" integer GENERATED BY DEFAULT AS IDENTITY,
    "Dates" tsrange[] NULL,
    CONSTRAINT "PK_Blogs" PRIMARY KEY ("Id")
);

您可能对即将发布的 PostgreSQL 14 版本中的新多范围类型感兴趣。对它的支持已添加到 EF Core 提供程序的 6.0 版中(PG14 和 EF Core 6.0.0 的候选版本已经发布),因此您可能想尝试一下。

我收到这个 'not a supported primitive type' 错误是因为我按照我的情况遵循了错误的文档。我从 https://www.npgsql.org/doc/types/nodatime.html 开始,它使用 NuGet 包 Npgsql.NodaTime 并使用 NpgsqlConnection.GlobalTypeMapper.UseNodaTime();

应用类型映射

我需要改为遵循 https://www.npgsql.org/efcore/mapping/nodatime.html 处的 EF Core 文档,它依赖于 NuGet 包 Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime 并通过 UseNodaTime()NpgsqlDbContextOptionsBuilder 上应用类型映射

builder.UseNpgsql("Host=localhost;Database=test;Username=npgsql_tests;Password=npgsql_tests",
        o => o.UseNodaTime());