3

У меня есть две таблиц в унаследованных базах данных (которые я не могу изменить) с данными следующим образом:таблицы на иерархию и составного первичного ключ

two legacy tables

Table1 имеет составной первичный ключ (код, Abbrev), но Abbrev также используется в качестве дискриминатора (см. ниже). Таблица 2 имеет два столбца внешнего ключа (CodeA, CodeB), которые ссылаются на один и тот же код поля в таблице 1. В поле Table1.Code есть дубликаты.

Я хотел бы использовать таблицу на иерархический подход с каркасом Entity 6. Итак, я создал следующие классы моделей:

[Table("Table1")] 
public class MyBaseClass 
{ 
    [Key] 
    public string Code { get; set; } 
} 

public class MyBaseClassA : MyBaseClass 
{ 
} 

public class MyBaseClassB: MyBaseClass 
{ 
} 

[Table("Table2")] 
public class SubClass 
{ 
    [Key] 
    public int Id { get; set; } 

    [Required] 
    [ForeignKey("MyBaseClassA")] 
    public string CodeA { get; set; } 

    public virtual MyBaseClassA ClassA { get; set; } 

    [Required] 
    [ForeignKey("MyBaseClassB")] 
    public string CodeA { get; set; } 

    public virtual MyBaseClassB ClassB { get; set; } 

} 

Я определил таблица за иерархии в моей DataContext: DbContext класс, как следующим образом:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<MyBaseClass>().Map<MyBaseClassA>(m => m.Requires("Abbrev").HasValue("A")) 
      .Map<MyBaseClassB>(m => m.Requires("Abbrev").HasValue("B")); 
    } 

проблема заключается в том, когда я хочу использовать такое отображение - я не могу использовать поле дискриминатора (Table1.Abbrev) в качестве части составного ключа в MyBaseClass - я получаю следующее сообщение об ошибке:

All objects in the EntitySet 'DataContext.MyBaseClass' must have unique primary keys. However, an instance of type 'MyBaseClassA' and an instance of type 'MyBaseClassB' both have the same primary key value, 'EntitySet=MyBaseClass;Code=1'.

Возможно ли сопоставить модель выше с платформой Entity 6 (или новее)?

+1

я думаю, что ваша модель таблица 1 неверна, вы сказали, что у вас есть составной ключ кода и аббревиатура, но в вашем сущности у вас есть только одна ключевая часть (код). – loiti

+0

В некотором смысле, это правильно, но я не могу иметь как отображение дискриминатора в классе DataContext, так и такое же свойство в модели (как часть составного ключа), EF отказывается от него. –

+1

Вам нужно изменить данные? Если вы просто читаете на них, вы можете определить виды, которые упрощают использование EF и лучше защищать их. – Rory

ответ

1

Я боюсь, что это невозможно с Entity Framework.

Для начала вам необходимо набрать полный ключ Table1, так как EF не может идентифицировать только Table1 объектов по Code. И дискриминатор, который является частью составного первичного ключа, просто не поддерживается.

Таким образом, вы не можете подтип Table1. Теперь, если это все, вы можете не использовать наследование. Но Table2 - настоящий демпфер. EF требует, чтобы внешние ключи ссылались на первичный ключ . Итак, поскольку Table1 должен иметь составной ключ, то два внешних ключа Table2 также должны выглядеть как { Code, Abbrev }. Ну, нет ни одного поля Abbrev в Table2.

Единственное, что вы можете сделать, это карта Table1 как есть (без наследования), а также Table2 без какой-либо связи между ними. Вам придется вручную писать объединения (из родов) для получения связанных записей из базы данных в одном запросе.

Например, чтобы получить Table2 с Table1 в A:

from t1 in context.Table1s 
join t2 in context.Table2s on t1.Code equals t2.CodeA 
where t1.Abbrev == "A" 
select new { A = t1, t2 } 

Или Table2 с одновременно Table1 в A и Table1 в B:

from t2 in context.Table2s 
select new 
{ 
    t2, 
    A = (from t1 in context.Table1s 
     where t1.Code == t2.CodeA && t1.Abbrev == "A") 
     .FirstOrDefault(), 
    B = (from t1 in context.Table1s 
     where t1.Code == t2.CodeB && t1.Abbrev == "B") 
     .FirstOrDefault(), 
} 
0

Создайте новую таблицу, в которой в качестве первичного ключа используется столбец «Аббревиатура». (Эта таблица будет иметь только две строки в вашем примере с значениями столбца «Аббревиатура» «A» и «B».) Затем определите отношение внешнего ключа между этой новой таблицей и существующей таблицей 1. В коде обновите MyBaseClass для Table1, добавив столбец «Аббревиатура» как часть существующего определения первичного ключа.

Это должно устранить ошибку «должно иметь уникальные первичные ключи», генерируемое MyBaseClass.

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