【问题标题】:EF Core NodaTime field - could not be mappedEF Core NodaTime 字段 - 无法映射
【发布时间】:2021-11-18 04:36:13
【问题描述】:

我将 EF Core 与 <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="5.0.2" /> 一起使用

我刚刚向我的实体添加了一个 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:属性“EventItem.Dates”不能 已映射,因为它的类型为 List&lt;NpgsqlRange&lt;LocalDateTime&gt;&gt;,不受支持 原始类型或有效的实体类型。要么明确地映射这个 属性,或使用“[NotMapped]”属性或使用 “OnModelCreating”中的“EntityTypeBuilder.Ignore”。

所以 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&lt;NpgsqlRange&lt;LocalDateTime&gt;&gt;

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

仅供参考,我的前端正在向后端发送自定义对象列表:[{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,所以我想我会在这里发布他的解决方案,使用ConfigureServices语法,供那些代码已经使用ConfigureServices的人使用:

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

【问题讨论】:

  • 值转换器限制太多。您是否使用 EF Core 特定的 NodaTime 插件,例如 nuget.org/packages/…?它应该为 NodaTime 类型提供必要的EF Core mappings
  • @IvanStoev 是的。我意识到我需要List&lt;NpgsqlRange&lt;LocalDateTime&gt;&gt; 而不是因为我需要时间而不仅仅是日期。我已经更新了整个问题,虽然同样的问题仍然存在,但 EF Core 无法映射该字段。临时解决方法是使用List&lt;NpgsqlRange&lt;System.DateTime&gt;&gt;(所以根本没有 NodaTime)。

标签: datetime entity-framework-core npgsql nodatime asp.net5


【解决方案1】:

以上内容适用于我,使用 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; }
}

创建了下表:

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 的候选版本已经推出),因此您可能想尝试一下。

【讨论】:

  • 谢谢,它有效!我已将错误的 Startup.cs 代码与您的解决方案一起添加到问题的底部,同时应用于我的应用正在使用的 ConfigureServices 样式。
猜你喜欢
  • 2022-01-25
  • 1970-01-01
  • 2015-01-13
  • 2021-05-01
  • 1970-01-01
  • 2021-06-14
  • 1970-01-01
  • 1970-01-01
  • 2020-01-01
相关资源
最近更新 更多