Мне нужно преобразовать некоторую существующую БД в новое приложение, используя EF6 с подходом CodeFirst. Я борюсь с соглашениями об отображении в наследовании. Существует минимальный (не) рабочий пример:Entity framework 6 настраиваемых ключей для наследования типа таблицы за тип
Предположим, у меня есть две таблицы: родитель и ребенок.
CREATE TABLE A_PARENT (
A_PAR_ParentId UNIQUEIDENTIFIER PRIMARY KEY,
A_PAR_data VARCHAR(255)
)
CREATE TABLE B_CHILD (
B_CHL_ChildId UNIQUEIDENTIFIER PRIMARY KEY FOREIGN KEY REFERENCES A_PARENT(A_PAR_ParentId),
B_CHL_childData VARCHAR(255)
)
Я успешно решала таблицу prefices вы можете видеть, такое «A_PAR» с использованием пользовательских атрибутов. Я считаю, что EF точно знает, какое свойство принадлежит тому столбцу, а какой - первичный ключ. Все работает отлично, за исключением наследования. Потому что, когда я пытаюсь получить все дети, я в конечном итоге с ошибкой SQL, так как EF производит запрос следующим образом:
SELECT
'0X0X' AS [C1],
[Extent1].[A_PAR_ParentId] AS [A_PAR_ParentId],
[Extent1].[A_PAR_Data] AS [A_PAR_Data],
[Extent2].[B_CHL_ChildId] AS [B_CHL_ChildId],
[Extent2].[B_CHL_ChildData] AS [B_CHL_ChildData]
FROM [dbo].[A_PARENT] AS [Extent1]
INNER JOIN [dbo].[B_CHILD] AS [Extent2] ON [Extent1].[A_PAR_ParentId] = [Extent2].[A_PAR_ParentId]
только неправильно, что в запросе является Предикат - там нет такого столбец A_PAR_ParentId
в таблице B_CHILD
.
Как я могу заставить EntityFramework использовать первичный ключ сущности для использования в качестве внешнего ключа при построении цепочки наследования? Я ищу какое-то общее решение, основанное на соглашениях, потому что все таблицы в БД используют этот шаблон (если тип/таблица наследуется => первичный ключ является внешним ключом к основному ключу родителя, и нет составных клавиш в все). Возможно, я ищу способ сообщить EF, что ПК также является FK, но без свойства навигации.
--edit: больше кода
модель довольно проста:
[ModulePrefix("A"), TablePrefix("PAR")]
public class Parent
{
public Guid ParentId { get; set; }
public string Data { get; set; }
}
[ModulePrefix("B"), TablePrefix("CHL")]
public class Child : Parent
{
public Guid ChildId { get; set; }
public string ChildData { get; set; }
}
И конфигурация:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Types()
.Where(type => !type.GetCustomAttributes(false).OfType<TableAttribute>().Any() && type.GetCustomAttributes(false).OfType<ModulePrefixAttribute>().Any())
.Configure(config => config.ToTable(
ComposeDbName(GetModulePrefix(config.ClrType),
CamelCaseToUnderscore(GetClassName(config.ClrType)).ToUpper())
));
modelBuilder.Properties()
.Where(property => property.DeclaringType.GetCustomAttributes(false).OfType<TablePrefixAttribute>().Any() && property.DeclaringType == property.ReflectedType)
.Configure(config => config.HasColumnName(ComposeDbName(
GetModulePrefix(config.ClrPropertyInfo.DeclaringType),
GetTablePrefix(config.ClrPropertyInfo.DeclaringType),
config.ClrPropertyInfo.Name
)));
modelBuilder.Properties()
.Where(property => property.Name == property.DeclaringType.Name + "Id" && property.ReflectedType == property.DeclaringType)
.Configure(config => config.IsKey());
modelBuilder.Properties()
.Where(property => property.PropertyType.IsClass || Nullable.GetUnderlyingType(property.PropertyType) != null)
.Configure(config => config.IsOptional());
}
Есть некоторые более частные методы играют с столбцами/именами таблиц , Я думаю, что это не важно на данный момент, так как имена столбцов/таблиц выглядят хорошо разрешенными.
Давайте рассмотрим первую модель/конфигурацию кода, связанную с приведенными выше таблицами. –
Я только что добавил код к вопросу. –
Поле 'Child.ChildId' вызывает проблему. –