代码之家  ›  专栏  ›  技术社区  ›  Ben

如何使用自定义类作为实体的属性,并使用实体框架核心进行转换?

  •  2
  • Ben  · 技术社区  · 7 年前

    我试图在我的应用程序中使用“每个层次表”对不同级别的帐户建模。基本上有三个级别的帐户:超级,合作伙伴和标准。他们都共享他们的大部分财产,但关键的区别是标准帐户由超级帐户或合作伙伴帐户管理。

    AccountType 属性 Account

    我的课程是这样安排的:

    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 只是一个将字符串解析为枚举值的小助手类):

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

    我可以从我的 在一个独立的类上工作(没有继承),但是当我尝试使用继承和每个层次的表时就不行了。这是不支持还是我做错了什么?

    0 回复  |  直到 7 年前