c# - 尝试使用 .Net Core 中的值转换器将模型中的 long 转换为具有多个字段的对象
问题描述
我正在制作一个连接到硬件的 .net 核心应用程序,该应用程序负责更新设置并将它们保存到数据库中。硬件和数据库中的所有时间值都以秒为单位存储为 long,但客户端希望时间可以在两个单独的字段(分钟和秒)中进行编辑,然后作为单个 long 值保存回数据库和机器。
我试图编写一个值转换器来将 long 转换为 MinutesAndSecondsTime 对象。但是,我不确定如何指定 MinutesAndSecondsTime 对象(或者是否可以完成),因为它会生成外键 id 并且无法引用。
模型(删除了附加字段)是:
public class Machine: BaseEntity
{
public long Delay { get; set; }
public MinutesAndSecondsTime SplitDelay { get; set; }
public long Runtime { get; set; }
public MinutesAndSecondsTime SplitRuntime { get; set; }
}
我试图将这些值转换为的对象如下:
public class MinutesAndSecondsTime
{
public MinutesAndSecondsTime(long time)
{
Minutes = time / 60;
Seconds = time % 60;
}
public long Minutes { get; set; }
public long Seconds { get; set; }
}
然后我有一个 TimeConverter 类,它应该处理转换:
public class TimeConverter : ValueConverter<long, MinuteSecondTime>
{
public TimeConverter(ConverterMappingHints mappingHints = null) :
base(convertToProviderExpression, convertFromProviderExpression,
mappingHints)
{ }
private static Expression<Func<long, MinuteSecondTime>> convertToProviderExpression = x => ToTimeObject(x);
private static Expression<Func<MinuteSecondTime, long>> convertFromProviderExpression = x => ToTimeLong(x);
private static MinuteSecondTime ToTimeObject(long time)
{
return new MinuteSecondTime(time);
}
private static long ToTimeLong(MinuteSecondTime time)
{
return time.Minutes * 60 + time.Seconds;
}
}
在 ApplicationDbContext 中,这应用于 OnModelCreating 函数:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
var entity = modelBuilder.Model.GetEntityTypes()
.Where(x => x.Name == "TestApp.Machine").First();
var delayProperty = entity.GetProperties().Where(y => y.Name == "Delay").First();
var runtimeProperty = entity.GetProperties().Where(y => y.Name == "Runtime").First();
delayProperty.SetValueConverter(new TimeConverter());
runtimeProperty.SetValueConverter(new TimeConverter());
}
我目前得到:
System.ArgumentException:“模型类型“MinuteSecondTime”的转换器不能用于“Article.Delay”,因为它的类型是“long”。
尝试将转换器添加到 OnModelCreating 中的字段时。据我所知,价值转换似乎只接受一个字段。有没有办法解决这个问题或替代解决方案?
解决方案
据我了解,您正在尝试做的是在数据库中有一个长数据类型,但它被转换为MinutesAndSecondsTime
.
我会将您的机器模型更改为如下所示:
public class Machine
{
[Key]
public int Id { get; set; }
[Column(TypeName = "integer")]
public MinutesAndSecondsTime Delay { get; set; }
[Column(TypeName = "integer")]
public MinutesAndSecondsTime Runtime { get; set; }
}
您可以将类型更改为int
或bigint
取决于您正在使用的数据库提供程序。我使用 SQLite。
ValueConverter
应该像这样实现:
public class TimeConverter : ValueConverter<MinutesAndSecondsTime, long>
{
public TimeConverter(ConverterMappingHints mappingHints = null) :
base(convertToProviderExpression, convertFromProviderExpression,
mappingHints)
{ }
private static Expression<Func<MinutesAndSecondsTime, long>> convertToProviderExpression = x => ToTimeLong(x);
private static Expression<Func<long, MinutesAndSecondsTime>> convertFromProviderExpression = x => ToTimeObject(x);
private static MinutesAndSecondsTime ToTimeObject(long time)
{
return new MinutesAndSecondsTime(time);
}
private static long ToTimeLong(MinutesAndSecondsTime time)
{
return time.Minutes * 60 + time.Seconds;
}
}
请注意,我将类型参数切换为TimeConverter
. 您可以在此处了解有关 ValueConverter的更多信息
然后你可以OnModelCreating
像这样实现:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Machine>()
.Property(e => e.Delay)
.HasConversion(new TimeConverter());
modelBuilder
.Entity<Machine>()
.Property(e => e.Runtime)
.HasConversion(new TimeConverter());
}
MinutesAndSecondsTime
然后当使用对象将值插入数据库时,如下所示:
db.Machines.Add(new Machine()
{
Delay = new MinutesAndSecondsTime(10000)
});
db.SaveChanges();
推荐阅读
- c++ - 为什么为 const std::vector 定义了 operator[],而不为 const std::map 定义了 operator[]?
- r - 查找两个不同时间之间是否存在时间,输入问题
- sql - 如何按特定日期和另一个标识符 SQL 对我的数据进行分区
- javascript - 如何检测谷歌身份验证登录用户是否是新用户或不使用firebase反应原生
- encoding - 为什么以及如何对电子邮件点击计数器链接进行编码
- sql - Mysql 和 SQL Server 的语法差异
- azure-functions - 在 terraform 部署期间强制更新 Azure 函数 zip 包
- c++ - 插入 C++ 映射会导致无限递归?
- r - 在 NAMESPACE 中使用“<-”注册 S3 方法
- android - 如何将图像从 url 保存到 assets 文件夹中