Отдельные свойства навигации для разных подтипов в иерархии TPH.C#

Место общения программистов C#
Ответить Пред. темаСлед. тема
Anonymous
 Отдельные свойства навигации для разных подтипов в иерархии TPH.

Сообщение Anonymous »

У меня есть модель «сначала код» Entity Framework 6 (v6.5.1), подобная этой (имена типов были изменены для анонимизации кода):

Код: Выделить всё

public abstract class Point
{
public long ID { get; set; }

public long PointSetID { get; set; }
public PointSet PointSet { get; set; }

public double X { get; set; }
public double Y { get; set; }
public double Z { get; set; }
}

public abstract class DetailedPoint : Point
{
public String Description { get; set; }
public Byte[] Data { get; set; }
}

public class Category1Point : Point
{
}

public class Category2Point: DetailedPoint
{
}

public class Category3Point : DetailedPoint
{
}

public class PointSet
{
public PointSet()
{
Category1Points = new HashSet();
Category2Points = new HashSet();
Category3Points = new HashSet();
}

public long ID { get; set; }

public virtual ICollection Points { get; set; }
public virtual ICollection Category1Points { get; set; }
public virtual ICollection Category2Points { get; set; }
public virtual ICollection Category3Points { get; set; }
}

public class PointContext : DbContext
{
public virtual DbSet Points { get; set; }
public virtual DbSet PointSets { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity()
.HasMany(e => e.Points)
.WithRequired(e => e.PointSet)
.HasForeignKey(e => e.PointSetID)
.WillCascadeOnDelete(true);
}
}
Три категории точек имеют одну и ту же модель данных, но не являются взаимозаменяемыми, поскольку представляют собой измерения разных видов вещей, поэтому у них разные конкретные классы.
Когда я запускаю Add-Migration, отношения между Point и PointSet формируются таким образом, что это выглядит довольно уродливо. Он создал три дополнительных столбца для дополнительных отношений внешнего ключа с отдельными индексами. Они должны быть избыточными, поскольку таблица базового класса Point уже имеет отношение внешнего ключа к PointSet.

Код: Выделить всё

   CreateTable(
"dbo.PointSets",
c => new
{
ID = c.Long(nullable: false, identity: true),
})
.PrimaryKey(t => t.ID);

CreateTable(
"dbo.Points",
c => new
{
ID = c.Long(nullable: false, identity: true),
PointSetID = c.Long(nullable: false),
X = c.Double(nullable: false),
Y = c.Double(nullable: false),
Z = c.Double(nullable: false),
Description = c.String(maxLength: 500),
Data = c.Binary(),
Discriminator = c.String(nullable: false, maxLength: 128),
PointSet_ID = c.Long(),
PointSet_ID1 = c.Long(),
PointSet_ID2 = c.Long(),
})
.PrimaryKey(t => t.ID)
.ForeignKey("dbo.PointSets", t => t.PointSet_ID)
.ForeignKey("dbo.PointSets", t => t.PointSet_ID1)
.ForeignKey("dbo.PointSets", t => t.PointSet_ID2)
.ForeignKey("dbo.PointSets", t => t.PointSetID, cascadeDelete: true)
.Index(t => t.PointSetID)
.Index(t => t.PointSet_ID)
.Index(t => t.PointSet_ID1)
.Index(t => t.PointSet_ID2);
Я пытался использовать OnModelCreating, чтобы заставить свойства навигации CategoryXPoints использовать существующее поле PointSetID в качестве внешнего ключа, например:
p>

Код: Выделить всё

            modelBuilder.Entity()
.HasMany(e => e.Points)
.WithRequired(e => e.PointSet)
.HasForeignKey(e => e.PointSetID)
.WillCascadeOnDelete(true);

modelBuilder.Entity()
.HasMany(e => e.Category1Points)
.WithRequired(e => e.PointSet)
.HasForeignKey(e => e.PointSetID)
.WillCascadeOnDelete(false);

modelBuilder.Entity()
.HasMany(e => e.Category2Points)
.WithRequired(e => e.PointSet)
.HasForeignKey(e => e.PointSetID)
.WillCascadeOnDelete(false);

modelBuilder.Entity()
.HasMany(e => e.Category3Points)
.WithRequired(e => e.PointSet)
.HasForeignKey(e => e.PointSetID)
.WillCascadeOnDelete(false);
Но когда я пытаюсь это сделать, Add-Migration выдает это исключение:

System.InvalidOperationException: Компонент внешнего ключа «PointSetID» не является объявленным свойством типа «Category1Point». Убедитесь, что оно не было явно исключено из модели и является допустимым примитивным свойством.

Я не понимаю, почему выдается это исключение, поскольку у класса абсолютно есть свойство PointSetID, которое является допустимым примитивом, и я определенно не исключал его явно из модели.
Если я удалю .HasForeignKey(e => e.PointSetID) вызывает OnModelBuilder(), вместо этого я получаю следующую ошибку:

PointSet: FromRole: NavigationProperty 'PointSet ' недействительно. Тип «Category3Point» FromRole «PointSet_Category3Points_Target» в AssociationType «PointSet_Category3Points» должен точно совпадать с типом «Point», для которого объявлено это свойство NavigationProperty.

Можно ли в таблице TPH настроить свойства навигации от одного класса к разным отдельным подтипам, не создавая кучу избыточные внешние ключи и индексы?

Подробнее здесь: https://stackoverflow.com/questions/793 ... -hierarchy
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «C#»