实体框架-如何将测试数据种子设定为使用按类型表继承的实体

本文关键字:实体 类型 继承 框架 种子 测试数据 | 更新日期: 2023-09-27 17:57:26

我首先使用EF5代码、迁移和按类型继承表。我有一些从其他类继承的类。例如,TenantLandlord继承自UserProfile

我正在使用protected override void Seed()方法将测试数据添加到我的数据库中。因此,例如,我创建了2个UserProfile对象和1个Tenant和1个Landlord。我如何确保租户实体与第一用户配置文件实体相关联,房东实体与第二用户配置文件主体相关联?因为我使用的是表每类型继承,所以我需要明确地说派生类的UserId等于其基类的UserId吗?我到处找了找,但找不到有用的东西。我试着这样做:

protected override void Seed(Context context)
    {
        var users = new List<UserProfile>
        {
             new UserProfile { UserId=1, UserName="Matt", Email="a@a.com", AccountType=AccountType.Tenant },
             new UserProfile { UserId=2, UserName="Dave", Email="a@a.com", AccountType=AccountType.Landlord }
        };
        users.ForEach(u => context.UserProfile.AddOrUpdate(u));
        context.SaveChanges();
        var tenants = new List<Tenant>
        {
            new Tenant { UserId = users.Single(x => x.UserId = 1) /* other properties */  }
            // ...
        };
        tenants.ForEach(t => context.Tenant.AddOrUpdate(t));
        context.SaveChanges();
        var landlords = new List<Landlord>
        {
            new Landlord { UserId = users.Single(x => x.UserId = 2) /* other properties */ }
            // ...
        };
        landlords.ForEach(l => context.Tenant.AddOrUpdate(l));
        context.SaveChanges();
    }

实体框架-如何将测试数据种子设定为使用按类型表继承的实体

您必须使用DbContext来加载要分配给它的实体。

这应该做到:

protected override void Seed(Context context)
    {
        var users = new List<UserProfile>
    {
         new UserProfile { UserId=1, UserName="Matt", Email="a@a.com", AccountType=AccountType.Tenant },
         new UserProfile { UserId=2, UserName="Dave", Email="a@a.com", AccountType=AccountType.Landlord }
    };
        users.ForEach(u => context.UserProfile.AddOrUpdate(u));
        context.SaveChanges();
        var tenants = new List<Tenant>
    {
        new Tenant { UserId = users.Single(x => x.UserId = context.UserProfile.First(x=>x.UserId = 1)) /* other properties */  }
        // ...
    };
        tenants.ForEach(t => context.Tenant.AddOrUpdate(t));
        context.SaveChanges();
        var landlords = new List<Landlord>
    {
        new Landlord { UserId = users.Single(x => x.UserId = context.UserProfile.First(x=>x.UserId = 2)) /* other properties */ }
        // ...
    };
        landlords.ForEach(l => context.Tenant.AddOrUpdate(l));
        context.SaveChanges();
    }

虽然Maximc有正确的想法,但我发现您可以使用DbContext.Set<T>方法为子类使用AddOrUpdate方法,而无需首先手动从数据库中获取它们:

protected override void Seed(Context context)
{            
    context.Set<Tenant>().AddOrUpdate(
        t => t.UserName, // or whatever property you want to use as an identifier for duplicates
        new Tenant { UserId=1, UserName="Matt", Email="a@a.com" });
    context.Set<Landlord>().AddOrUpdate(
        t => t.UserName,
        new Tenant { UserId=2, UserName="Dave", Email="a@a.com" });
}

此外,您可能不应该自己指定鉴别器(在您的案例中为AccountType)。当您正确设置POCO继承时,实体框架将在后台为您处理此问题。