Есть ли лучший способ достичь этой конечной цели - иметь легко запрашиваемые (и Include-able) сечения связанного объекта «многие ко многим», хранящиеся в одной и той же таблице?EF7 Внедрение TPH + M2M
Я начал без внедрения TPH в таблице соединений, но это делает потребление одного типа или другого в более привлекательных запросах, afaict.
// table Related: [Id]
public class Related
{
public Guid Id { get; set; }
public List<RelatedOther> RelatedOthers { get; set; } = new List<RelatedOther>();
public List<RelatedOtherOne> RelatedOtherOnes { get; set; } = new List<RelatedOtherOne>();
public List<RelatedOtherTwo> RelatedOtherTwos { get; set; } = new List<RelatedOtherTwo>();
}
// table RelatedOther: [RelatedId, OtherId, Type]
public abstract class RelatedOther
{
public Guid RelatedId { get; set; }
public Guid OtherId { get; set; }
public Related Related { get; set; }
public Other Other { get; set; }
public abstract RelatedOtherType Type { get; }
}
public class RelatedOtherOne : RelatedOther
{
public override RelatedOtherType Type => RelatedOtherType.One;
// should be unnecessary, 'Other' should be correct type
public OtherOne OtherOne { get; set; }
}
public class RelatedOtherTwo : RelatedOther
{
public override RelatedOtherType Type => RelatedOtherType.Two;
// should be unnecessary, 'Other' should be correct type
public OtherTwo OtherTwo { get; set; }
}
public enum RelatedOtherType : int
{
One = 1,
Two = 2
}
// table Other: [Id, OneProp, TwoProp]
public abstract class Other
{
public Guid Id { get; set; }
public List<RelatedOther> RelatedOthers { get; set; } = new List<RelatedOther>();
}
public class OtherOne : Other
{
public string OneProp { get; set; }
}
public class OtherTwo : Other
{
public string TwoProp { get; set; }
}
TPH отображается like this
M2M отображается like this + дискриминатор в HasKey()
Это становится еще более сложным (если не невозможно?), Когда объект в 'связанных с' перерастает в стратегию TPH как другой'.
Я решил, что если концы связи m2m являются TPH, тогда сама таблица соединений также должна отражать эту TPH, независимо от того, открываю ли я свойства навигации на обоих концах для всех этих типов TPH. Это просто более чистый дизайн. Затем это позволит платформе обрабатывать перевод свойства навигации, который у вас есть как «[NotMapped]» с использованием трансляции. – JoeBrockhaus
И когда я использую 'abstract' в моем базовом классе, это не мешает мне запрашивать только этот базовый тип - если запрос приводит к более чем одному производному типу в качестве результирующего набора, EF будет создавать экземпляр правильного производного типа и экземпляр в соответствующем производном типе будет автоматически заполнен этим экземпляром. Если ваша модель имеет 2 (и только 2) производных типа, то базовый класс должен быть абстрактным. Экземпляр Event2Location без значения дискриминатора EventType на самом деле не имеет смысла, правильно? Поэтому вы никогда не сможете создать ванильный экземпляр Event2Location. – JoeBrockhaus