我可以使用daterange列并与EF for PostgreSQL一起使用吗,c#?

时间:2019-03-27 08:59:11

标签: c# entity-framework npgsql

通常,我具有某个日期范围内的报告数据,并且我想插入新的数据,并删除同一时期的旧数据。

我想在postgresql db中使用daterange类型的列。 我正在为PostgreSQL使用最新版本的EF。 我希望能够将我的字段映射到某些属性。 我希望能够根据此列选择,删除和插入新内容。

我试图将上下文映射到: 公共NpgsqlRange month_year {get;组; } 但有一个例外:“列“ month_year”的类型为daterange,但表达式的类型为tsrange” –我知道它正在发生,因为映射是这样工作的:NpgsqlRange => tsrange

我尝试使用: NpgsqlRange 但是下一个例外: 属性“ DBTable1.DateRangeNoda”的类型为“ NpgsqlRange”,当前的数据库提供程序不支持该属性,但是这不应该已经起作用了吗? 所以我的问题是:在.net core中有没有办法使用EF的daterange类型的列?如何?

using (var context = new postgresContext())
{ 
    var d = new DBTable1(){Text = "aaa" };
    d.DateRange1 = new NpgsqlRange<DateTime>(DateTime.Today, DateTime.Today);

    //d.DateRangeNoda = new NpgsqlRange<LocalDate> 
    //                       (LocalDate.FromDateTime(DateTime.Today), 
    //                        LocalDate.FromDateTime(DateTime.Today) );
    //efNpgsqlDate>  not supported by provider

     context.dbTable1.Add(d); 

     context.SaveChanges();
}

public partial class DBTable1 
{
    [Column("id")]
    public int Id { get; set; }

    public NpgsqlRange<DateTime> DateRange0 { get; set; }

    public NpgsqlRange<LocalDate> DateRangeNoda { get; set; }
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<DBTable1>(entity =>
    {
    entity.ToTable("test1");

    entity.Property(e => e.DateRange1).HasColumnName("daterange1"); 

    entity.Property(e => e.DateRangeNoda).HasColumnName("daterange"); 

    }); 
}

现在我最终使用带有FirstOfTheRange date的date列:(

谢谢您的帮助,

2 个答案:

答案 0 :(得分:1)

上面的代码示例中似乎有些混乱-您正在访问属性DateRange1,而DBTable1类似乎包含DateRange0

Npgsql支持两种与日期/时间类型进行交互的方式:内置的BCL类型(例如DateTime)和the NodaTime library。支持内置的DateTime类型,但是默认将其映射到PostgreSQL timestamp而不是date,因为它具有时间分量。因此,类型为NpgsqlRange<DateTime>的属性将导致Npgsql创建一个tsrange列(时间戳范围),而不是daterange)。可以将daterange明确指定为列类型,但是与此相关的问题(see this comment会遇到一些细微问题。

如果使用NodaTime是可以的,那么事情应该会更好,因为NodaTime具有仅日期的类型-LocalDate-因此NpgsqlRange<LocalDate>自动映射到daterange。为此,您将需要使用NodaTime插件as specified in the docs

下面是一个完整的代码示例,用于在NodaTime中使用日期范围,包括插入和查询:

class Program
{
    static void Main(string[] args)
    {
        using (var ctx = new BlogContext())
        {
            ctx.Database.EnsureDeleted();
            ctx.Database.EnsureCreated();

            ctx.Blogs.Add(new Blog { Duration = new NpgsqlRange<LocalDate>(new LocalDate(2011, 1, 1), new LocalDate(2011, 1, 3)) });
            ctx.SaveChanges();

            var x = ctx.Blogs.FirstOrDefault(b => b.Duration.Contains(new LocalDate(2011, 1, 2)));
        }
    }
}

public class BlogContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        => optionsBuilder.UseNpgsql("<connection string>", o => o.UseNodaTime());

    public DbSet<Blog> Blogs { get; set; }
}

public class Blog
{
    public int Id { get; set; }
    public NpgsqlRange<LocalDate> Duration { get; set; }
}

答案 1 :(得分:0)

问题是NodaTime使用了错误的软件包:

<!--Wrong one <PackageReference Include="Npgsql.NodaTime" Version="4.0.5" /> --> <PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="2.2.0" /> 
<!--Good one --> 
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.NodaTime" Version="2.2.0" />