EF Code First: проблема при преобразовании ValueObject в строку для миграции - PullRequest
0 голосов
/ 03 августа 2020

Я следил за некоторыми руководствами, и объекты значений выглядят отлично, если я смогу заставить их работать, так что надеюсь, что вы, ребята, можете помочь.

У меня есть класс Account, содержащий объекты Value AccountNumber и SortCode (обратите внимание на BaseEntity только имеет int Id)

public class Account : BaseEntity
{
    public Account() => Transactions = new List<StatementTransaction>();

    public BankSortCode SortCode { get; set; }
    public BankAccountNumber AccountNumber { get; set; }
    public string AccountName { get; set; }
    public string BankName { get; set; }

    public ICollection<StatementTransaction> Transactions { get; set; }
    
}

BankSortCode и BankAccountNumber являются типами значений с определенными преобразованиями строк, например,

public class BankAccountNumber : ValueObject
{
    public string AccountNumber { get; private set; }

    public BankAccountNumber()
    {
    }

    public static BankAccountNumber For(string accountNumberString)
    {
        if (accountNumberString.Length <= 7 || accountNumberString.Length > 9)
        {
            throw new BankAccountNumberInvalidException(accountNumberString);
        }

        try
        {
            _ = Int32.Parse(accountNumberString);
        }
        catch (Exception ex)
        {
            throw new BankAccountNumberInvalidException(accountNumberString, ex);
        }

        var accountNumber = new BankAccountNumber();
        try
        {
            accountNumber.AccountNumber = accountNumberString;
        }
        catch (Exception ex)
        {
            throw new BankAccountNumberInvalidException(accountNumberString, ex);
        }

        return accountNumber;
    }

    public override string ToString()
    {
        return AccountNumber;
    }

    public static implicit operator string(BankAccountNumber accountNumber)
    {
        return accountNumber.ToString();
    }

    public static explicit operator BankAccountNumber(string accountNumberString)
    {
        return For(accountNumberString);
    }

    protected override IEnumerable<object> GetAtomicValues()
    {
        yield return AccountNumber;
    }
}

Я намереваюсь хранить их в БД как строковые поля для класса учетной записи , поэтому настройте modelBuilder в моем DBContext следующим образом:

private void ConfigureAccount(ModelBuilder modelBuilder)
    {
        modelBuilder
        .Entity<Account>()
        .Property(a => a.SortCode)
        .HasColumnType("varchar")
        .HasMaxLength(6)
        .HasConversion<string>();

        modelBuilder
        .Entity<Account>()
        .Property(a => a.AccountNumber)
        .HasColumnType("varchar")
        .HasMaxLength(9)
        .HasConversion<string>();
    }

Однако, когда я пытаюсь добавить миграцию, я получаю следующую ошибку:

The property 'Account.AccountNumber' is of type 'BankAccountNumber' which is not supported by current database provider. Either change the property CLR type or ignore the property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.

Подхожу ли я к этому в правильный путь, и как мне решить проблему, с которой я столкнулся?

1 Ответ

0 голосов
/ 03 августа 2020

Похоже, у меня все заработало, копируя Павел Герр на Think Tecture .

HasConfiguration (howToTransformForInsert, howToTransforForRetrieve):

private void ConfigureAccount(ModelBuilder modelBuilder)
    {
        modelBuilder
        .Entity<Account>()
        .Property(a => a.SortCode)
        .HasColumnType("varchar")
        .HasMaxLength(6)
        .HasConversion(sortCode => sortCode.ToString(), sortCodeString => BankSortCode.For(sortCodeString));

        modelBuilder
        .Entity<Account>()
        .Property(a => a.AccountNumber)
        .HasColumnType("varchar")
        .HasMaxLength(9)
        .HasConversion(accountNumber => (string)accountNumber, accountNumberString => BankAccountNumber.For(accountNumberString));
    }
...