Как использовать пользовательский класс в качестве свойства сущности с преобразованием с помощью Entity Framework Core? - PullRequest
0 голосов
/ 05 февраля 2019

Я пытаюсь смоделировать учетные записи разных уровней, используя «Таблицу на иерархию» в моем приложении.В основном есть 3 уровня аккаунта: Super, Partner и Standard.Все они имеют большую часть своих свойств, но ключевое отличие заключается в том, что стандартные учетные записи управляются учетной записью Super или Partner.

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

Вот как устроены мои классы:

public abstract class Account
{
    [Key]
    public int Id { get; set; }

    [Required]
    public AccountTypeClass AccountType { get; set; }

    // other props omitted for brevity
}

public class StandardAccount : Account
{
    [Required]
    public int ManagingAccountId { get; set; }

    [ForeignKey(nameof(ManagingAccountId))]
    public ManagingAccount ManagingAccount { get; set; }
}

public abstract class ManagingAccount : Account
{
    public ICollection<StandardAccount> Accounts { get; set; } = new List<StandardAccount>();
}

public class PartnerAccount : ManagingAccount { }

public class SuperAccount : ManagingAccount { }

public class AccountTypeClass
{
    // other props omitted for brevity

    private string value;

    private AccountTypeClass(string value) => this.value = value;

    public static AccountTypeClass Super => new AccountTypeClass(nameof(Super).ToLower());
    public static AccountTypeClass Partner => new AccountTypeClass(nameof(Partner).ToLower());
    public static AccountTypeClass Standard => new AccountTypeClass(nameof(Standard).ToLower());

    public static AccountTypeClass Parse(string value)
    {
        switch(value)
        {
            case "super": return Super;
            case "partner": return Partner;
            case "standard": return Standard;
            default: throw new NotImplementedException();
        }
    }

    public override string ToString() => this.value;
}

Иэто мой DbContext:

public class DataContext : DbContext
{
    public DataContext(DbContextOptions options) : base(options)
    {
    }

    public virtual DbSet<Account> Accounts { get; set; }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        builder
            .Entity<Account>()
            .Property(p => p.AccountType)                    
            .HasConversion(p => p.ToString(), p => AccountTypeClass.Parse(p));

        builder.Entity<SuperAccount>().HasData(new SuperAccount() { Id = 1 });
        builder.Entity<PartnerAccount>().HasData(new PartnerAccount() { Id = 2 });
        builder.Entity<StandardAccount>().HasData(new StandardAccount() { Id = 3, ManagingAccountId = 1 });
    }
}

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

Невозможно добавить свойство или навигацию «AccountType» втип сущности 'ManagingAccount', так как свойство или навигация с таким же именем уже существует в типе сущности 'Account'.

Но если я поменяю AccountTypeClass для этого перечисления:

public enum AccountTypeEnum { Super, Partner, Standard }

И измените преобразование на это (где EnumHelper - это просто маленький вспомогательный класс, который анализирует строку до значения enum):

builder
    .Entity<Account>()
    .Property(p => p.AccountType)                    
    .HasConversion(p => p.ToString(), p => EnumHelper.Parse<AccountTypeEnum>(p));

Все работает, как и ожидалось.

Я могу получить преобразование в / из моего AccountTypeClass для работы в автономном классе (без наследования), но не тогда, когда я пытаюсь использовать наследование и таблицу для иерархии.Это не поддерживается или я сделал что-то не так?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...