Попытка использовать конвертер значений в .Net Core для преобразования длинного в модели в объект с несколькими полями - PullRequest
0 голосов
/ 24 октября 2019

Я делаю ядро ​​.net, которое подключается к аппаратному обеспечению, оно отвечает за обновление настроек и сохранение их в базе данных. Все значения времени на оборудовании и в базе данных сохраняются как длинные в секундах, но клиент хотел бы, чтобы время редактировалось в двух отдельных полях, минутах и ​​секундах, а затем сохранялось обратно в базу данных и машину как одно длинное значение.

Я попытался написать конвертер значений для преобразования объекта long в объект MinutesAndSecondsTime. Однако я не уверен, как указать объект MinutesAndSecondsTime (или, если это вообще возможно), так как он генерирует идентификатор иностранного ключа и на него нельзя ссылаться.

Модель (с удалением дополнительных полей)):

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. Из того, что я могу сказать, преобразование значений, кажется, принимает только одно поле. Есть ли способ обойти это или альтернативное решение?

1 Ответ

0 голосов
/ 24 октября 2019

Насколько я понимаю, вы пытаетесь сделать так, чтобы в базе данных был длинный тип данных, но он конвертируется в 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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...