Я работаю над базой данных для летающего клуба, в котором есть стол для рейсов и стол для членов клуба. Полеты, к сожалению, должны быть оплачены, так что есть BillTo, который ссылается на ClubMember, который должен заплатить.Иерархии наследования в структуре Entity
До сих пор это выглядит ...
public ClubMember
{
public int ID{get;set;}
public string FirstName{get;set;}
public string LastName {get;set;}
}
public Flight
{
public int ID {get;set;}
public ClubMember PilotPayingTheBill{get;set;}
public double EnormousPriceToBePaid {get;set;}
}
Довольно просто ... но грязный мир вмешается. Иногда самолет перевозится механиком для целей технического обслуживания. Я не хочу делать это ленивым путем и вводить механика в качестве фиктивной записи в таблице ClubMember. База данных слишком полезна для такого типа kludge. Кроме того, EF имеет изящную возможность реализовать наследование в базе данных, так что я могу держать все это красиво и аккуратно, как это:
public BillableEntity
{
public int ID{get;set;}
}
ClubMember : BillableEntity
{
public string FirstName{get;set;}
public string LastName {get;set;}
}
NonPayingUser : BillableEntity
{
public string Description {get;set;}
}
public Flight
{
public int ID {get;set;}
public BillableEntity billTo{get;set;}
public double EnormousPriceToBePaid {get;set;}
}
с несколькими инструкциями в моей беглой конфигурации NonPayingUser и ClubMembers все положить в свои собственные таблицы с идентификатором в качестве первичного ключа и внешнего ключа - приятный, сжатый дизайн. Я был очень доволен. Столбец Billto_id в таблице полетов не является нулевым, поэтому каждый рейс всегда будет иметь оплачиваемый статус, который будет либо членом клуба, либо NonPayingUser.
Дать запрос в TSQL довольно легко
select coalesce(cm.FirstName + ' ' + cm.LastName,np.Description) as BillTo
from Flights f
left outer join ClubMembers cm on f.billto_id = cm.ID
left outer join NonPayingUsers np on f.billto_id = np.ID
Но делать то же самое в EF имеет меня в тупик. Класс Flight имеет свойство BillTO, которое является родительским классом BillableEntity. Я могу отдать его в классы потомков, подобные этому ...
var flights = DB.Flights
.Select(f => new
{
PersonName = (f.BillTo as ClubMember).FirstName + PersonName = (f.BillTo as ClubMember).LastName
,
OtherName = (f.BillTo as NonPayingUser).Description
});
но это производит чудовищные количества TSQL.
Одним из решений является просто написать собственные хранимые процедуры для объединения этих таблиц и использовать классы EF для выполнения всех основных CRUD на отдельных таблицах, и это направление, в котором я склоняюсь. Но есть ли лучше путь?
Какое унаследование вы используете? Table-Per-Hierarchy (TPH), Table-Per-Type (TPT) или Table-Per-Concrete Class (TPC)? –
Таблица на тип наследования –