Entity Framework - как заполнить тестовые данные объектами, которые используют наследование таблиц для типов?
Я использую код EF5, миграцию и наследование таблиц. У меня есть некоторые классы, которые наследуются от других классов. Например Tenant
а также Landlord
наследовать от 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();
}
2 ответа
Вы должны использовать 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) самостоятельно. Entity Framework будет обрабатывать это для вас в фоновом режиме, когда вы правильно настроите наследование POCO.