C# 在SQLlite中将列映射到DateTime属性时,如何忽略字符串空值?
我使用实体框架从C#控制台应用程序读取SQLite数据库 问题是:我有许多列包含空字符串(例如:“”),并且映射到C#中的DateTime属性 当我试图读取这些记录时,这里是我得到的错误: 最内层异常System.FormatException:字符串“”为 无法识别为有效的日期时间。在 System.DateTimeParse.Parse(只读span`1 s,DateTimeFormatInfo dtfi, DateTimeStyles(样式)位于 Microsoft.Data.Sqlite.SqliteValueReader.GetDateTime(Int32序号) 将列映射到可为空的DateTime并不能解决此问题 显而易见的解决方案是清除所有这些空字符串,并用空值替换它们。在我的例子中,这不是小事,我不能保证将来不会有任何其他字符串空值 令人惊讶的是,如果映射到整数的列包含空字符串值,则该列可以工作(值映射到“0”) 在映射到DateTime时,有没有办法忽略这些空字符串值?(例如:它将返回空日期或DateTime.MinValue)。注意:我使用ISO 8601格式,而不是刻度 编辑: 这是我的密码C# 在SQLlite中将列映射到DateTime属性时,如何忽略字符串空值?,c#,entity-framework,sqlite,datetime,C#,Entity Framework,Sqlite,Datetime,我使用实体框架从C#控制台应用程序读取SQLite数据库 问题是:我有许多列包含空字符串(例如:“”),并且映射到C#中的DateTime属性 当我试图读取这些记录时,这里是我得到的错误: 最内层异常System.FormatException:字符串“”为 无法识别为有效的日期时间。在 System.DateTimeParse.Parse(只读span`1 s,DateTimeFormatInfo dtfi, DateTimeStyles(样式)位于 Microsoft.Data.Sqlite
public class FooContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder builder) {
builder.UseSqlite("Data Source=Database.db");
}
public DbSet<Bar> Bar { get; set; }
}
public class Bar
{
public int ID { get; set; }
public DateTime? SomeDate { get; set; }
}
using(FooContext context = new FooContext())
{
var bar = context.Find<Bar>(id); //throw exception
}
公共类FooContext:DbContext
{
配置时受保护的覆盖无效(DbContextOptionsBuilder){
builder.UseSqlite(“数据源=Database.db”);
}
公共DbSet条{get;set;}
}
公共类酒吧
{
公共int ID{get;set;}
公共日期时间?SomeDate{get;set;}
}
使用(FooContext=newfoocontext())
{
var bar=context.Find(id);//抛出异常
}
您可能必须在上下文类的OnModelCreating
方法上处理此问题。实际上,您必须重写此方法。在此方法中,我们创建了一个转换器,用于转换从数据库中读取的属性SomeDate
的值:
public class FooContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder builder) {
builder.UseSqlite("Data Source=Database.db");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
DateTime parsedDateTime;
var converter = new ValueConverter<string, DateTime?>(
v => string.IsNullOrWhiteSpace(v)
? null
: DateTime.TryParse(v, out parsedDateTime)
? parsedDateTime
: (DateTime?) null,
v => v != null
? v.ToString()
: string.Empty);
modelBuilder
.Entity<Bar>()
.Property(b=>b.SomeDate)
.HasConversion(converter);
}
public DbSet<Bar> Bar { get; set; }
}
公共类FooContext:DbContext
{
配置时受保护的覆盖无效(DbContextOptionsBuilder){
builder.UseSqlite(“数据源=Database.db”);
}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
日期时间解析数据时间;
var转换器=新值转换器(
v=>string.IsNullOrWhiteSpace(v)
无效的
:DateTime.TryParse(v,out-parsedDateTime)
?解析时间
:(日期时间?)空,
v=>v!=null
?v.ToString()
:string.Empty);
建模者
.实体()
.Property(b=>b.SomeDate)
.转换(转换器);
}
公共DbSet条{get;set;}
}
您可以阅读更多关于值转换的内容。您可能必须在上下文类的
OnModelCreating
方法中处理此问题。实际上,您必须重写此方法。在此方法中,我们创建了一个转换器,用于转换从数据库中读取的属性SomeDate
的值:
public class FooContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder builder) {
builder.UseSqlite("Data Source=Database.db");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
DateTime parsedDateTime;
var converter = new ValueConverter<string, DateTime?>(
v => string.IsNullOrWhiteSpace(v)
? null
: DateTime.TryParse(v, out parsedDateTime)
? parsedDateTime
: (DateTime?) null,
v => v != null
? v.ToString()
: string.Empty);
modelBuilder
.Entity<Bar>()
.Property(b=>b.SomeDate)
.HasConversion(converter);
}
public DbSet<Bar> Bar { get; set; }
}
公共类FooContext:DbContext
{
配置时受保护的覆盖无效(DbContextOptionsBuilder){
builder.UseSqlite(“数据源=Database.db”);
}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
日期时间解析数据时间;
var转换器=新值转换器(
v=>string.IsNullOrWhiteSpace(v)
无效的
:DateTime.TryParse(v,out-parsedDateTime)
?解析时间
:(日期时间?)空,
v=>v!=null
?v.ToString()
:string.Empty);
建模者
.实体()
.Property(b=>b.SomeDate)
.转换(转换器);
}
公共DbSet条{get;set;}
}
您可以阅读有关值转换的更多信息。请输入您用于读取所述记录的代码,好吗?感谢您编辑了问题您使用的是哪一版本的EF?@Aldert我使用的是Microsoft.EntityFrameworkCore.Sqlite 2.1您能用代码阅读您提到的记录吗?谢谢您编辑了问题您使用的是哪个版本的EF?@Aldert我使用的是Microsoft.EntityFrameworkCore.Sqlite 2.1有没有办法为所有日期时间字段设置名为的转换器?(因此我不必硬编码所有表的所有可能字段的hascoveration()调用)。我知道我可以通过思考来做到这一点,但也许有更好的方法。@tigrou我不知道有这样的事情。我也搜索了一下,什么也没找到。但是,与使用反射相比,使用EFCore提供的API显式声明更好。是否有方法为所有日期时间字段设置调用的转换器?(因此我不必硬编码所有表的所有可能字段的hascoveration()调用)。我知道我可以通过思考来做到这一点,但也许有更好的方法。@tigrou我不知道有这样的事情。我也搜索了一下,什么也没找到。但是,IMHO最好使用EFCore提供的API显式声明,而不是使用反射。