Я пытаюсь смоделировать учетные записи разных уровней, используя «Таблицу на иерархию» в моем приложении.В основном есть 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
для работы в автономном классе (без наследования), но не тогда, когда я пытаюсь использовать наследование и таблицу для иерархии.Это не поддерживается или я сделал что-то не так?