Я получаю это сообщение об ошибке при использовании EF Core для запроса данных:
System.InvalidCastException: невозможно привести временную метку типа базы данных без часового пояса к DateOnly
Это пример кода, который вызывает ошибку при использовании AddDay()
Затем я нашел проблему на github, но она была решена в .NET 8. Есть ли способ сделать это в .NET 6?
https://github.com/npgsql/efcore.pg/issues/2888
using Microsoft.EntityFrameworkCore;
using Npgsql;
using Xunit;
namespace DateOnlyNpgsql;
public class TestEntity
{
public int Id { get; set; }
public DateOnly Date { get; set; }
public int Diff { get; set; }
}
public class MyTest
{
[Fact]
public async Task InvalidCastExample()
{
var x = new DbCtx();
await x.Database.EnsureDeletedAsync();
await x.Database.EnsureCreatedAsync();
var e = new TestEntity()
{
Id = 1,
Date = DateOnly.Parse("2023-09-26"),
Diff = 1
};
x.TestEntities.Add(e);
await x.SaveChangesAsync();
var query = x.TestEntities
.Select(x => new
{
x.Id,
NextMonth = x.Date.AddDays(x.Diff)
});
// System.InvalidCastException: Can't cast database type timestamp without time zone to DateOnly
var a1 = query.ToArray();
}
}
public class DbCtx : DbContext
{
public DbSet<TestEntity> TestEntities { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseNpgsql(
new NpgsqlConnection("Host=localhost;Uid=postgres;Pwd=mysecretpassword;Database=DummyDatabase"));
}
Поскольку вы поделились ссылкой на известную проблему, вы можете видеть, что проблема устранена в версии .net 8, если вы все еще используете .net 6, я хотел бы предложить вам перейти на .net, чтобы решить проблему, или если вы все еще хотите Чтобы использовать .net 6, вы можете использовать приведенный ниже обходной путь, в котором используйте DateTime
и обработайте преобразование в DateOnly
в логике вашего приложения. Это позволяет избежать проблемы приведения при взаимодействии с базой данных.
Вы можете попробовать этот код ниже:
Программа.cs:
using System;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Npgsql;
using DateOnlyNpgsql.Models;
using DateOnlyNpgsql.Data;
namespace DateOnlyNpgsql
{
class Program
{
static async Task Main(string[] args)
{
var db = new DbCtx();
await db.Database.EnsureDeletedAsync();
await db.Database.EnsureCreatedAsync();
var entity = new TestEntity
{
Id = 1,
Date = DateTime.SpecifyKind(DateTime.Parse("2023-09-26"), DateTimeKind.Utc),
Diff = 1
};
db.TestEntities.Add(entity);
await db.SaveChangesAsync();
var query = db.TestEntities
.Select(x => new
{
x.Id,
NextMonth = DateOnly.FromDateTime(x.Date.AddDays(x.Diff))
});
var results = query.ToArray();
foreach (var result in results)
{
Console.WriteLine($"Id: {result.Id}, NextMonth: {result.NextMonth}");
}
}
}
}
MyTest.cs:
using Microsoft.EntityFrameworkCore;
using Npgsql;
using Xunit;
using System;
using System.Linq;
using System.Threading.Tasks;
using DateOnlyNpgsql.Models;
using DateOnlyNpgsql.Data;
namespace DateOnlyNpgsql.Tests
{
public class MyTest
{
[Fact]
public async Task InvalidCastExample()
{
var x = new DbCtx();
await x.Database.EnsureDeletedAsync();
await x.Database.EnsureCreatedAsync();
var e = new TestEntity()
{
Id = 1,
Date = DateTime.Parse("2023-09-26"),
Diff = 1
};
x.TestEntities.Add(e);
await x.SaveChangesAsync();
var query = x.TestEntities
.Select(x => new
{
x.Id,
NextMonth = DateOnly.FromDateTime(x.Date.AddDays(x.Diff))
});
var a1 = query.ToArray();
Assert.NotNull(a1);
Assert.Single(a1);
Assert.Equal(new DateOnly(2023, 09, 27), a1[0].NextMonth);
}
}
}
Результат: