2015-12-11 2 views
1

Я работаю над базой данных для летающего клуба, в котором есть стол для рейсов и стол для членов клуба. Полеты, к сожалению, должны быть оплачены, так что есть 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 на отдельных таблицах, и это направление, в котором я склоняюсь. Но есть ли лучше путь?

+0

Какое унаследование вы используете? Table-Per-Hierarchy (TPH), Table-Per-Type (TPT) или Table-Per-Concrete Class (TPC)? –

+0

Таблица на тип наследования –

ответ

0

Это дубликат нескольких подобных вопросов ...

EF (6, я смотрю на 7 RC1 сейчас) всегда порождает огромное количество TSQL.

Я думаю, что лучший ответ - это проблема «создания чудовищных сумм TSQL»?
Если у вас есть какая-то проблема с запросом, решите эту проблему, в противном случае проигнорируйте ее. Вы увидите, что в огромном проценте случаев это не вызывает проблем с СУБД.

0

Я в конечном итоге создать вычисляемое поле в таблице BillableEntities

alter table BillableEntities drop column name; 
    alter table BillableEntities add Name as (case when [Description] is null then LastName + ', ' + FirstName else [Description] end) 

и помечаются как DataBaseGenerated в классе BIllableEntities.

[DatabaseGenerated(DatabaseGeneratedOption.Computed)] 
    public string FullName { get; private set; } 

Таким образом, SQL, созданный EF, более управляем. Производительность хорошая, целостность данных тоже хороша.

Смежные вопросы