У меня следующая проблема с использованием генерации и наследования reversepoco из существующей БД. Я унаследовал базу данных и код, который был создан в рамках подхода Devart Model с использованием EF6. У меня есть задание - сначала сделать его Code, чтобы можно было использовать систему миграции CF. БД должна оставаться обратно совместимой.
Для преобразования в CF я использовал генерацию Reverse POCO от Саймона Хьюза. Саймон сделал несколько обновлений для включаемого файла, чтобы включить абстрактные классы и наследование.
На этом этапе я могу создать контекст и получить большую часть данных.
Проблема заключается в том, что БД не соблюдает правильные правила именования CF для FK. Я мог бы исправить 1 уровень наследования, добавив сопоставление в свободный конфигурационный код Api, но когда у меня есть второй или 3 уровень наследования, я не могу получить правильное сопоставление.
На этом этапе я получаю EF исключения, что имена таблиц не найдены: SqlException: недопустимое имя столбца «ReportData_Id». Неверное имя столбца «CompareDataValue_Id». Неверное имя столбца 'DataValue_Id'. Неверное имя столбца «ReportData_Id». Неверное имя столбца 'TextValue_Id'. Неверное имя столбца «ReportData_Id». ...
В следующей части я покажу модель БД (часть), таблицы, классы POCO и конфигурацию. Это много информации, но я хотел дать много информации по мере необходимости. Путь наследования, к которому я хотел бы обратиться: ReportData (базовый класс с идентификатором) -> ReturnData -> DataValue -> CompareDataValue
Таблицы :
Классы POCO`1: ReportData
[GeneratedCode("EF.Reverse.POCO.Generator", "v3.1.3")]
// ReportDatas
public partial class ReportData
{
public int Id { get; set; } // Id (Primary key)
public DateTime Timestamp { get; set; } // Timestamp
public int TestStep_Id { get; set; } // TestStep_Id
// Reverse navigation
/// <summary>
/// Parent (One-to-One) ReportData pointed by [ReportDatas_DataBlob].[Id] (FK_DataBlob_inherits_ReportData)
/// </summary>
public virtual DataBlob DataBlob { get; set; } // ReportDatas_DataBlob.FK_DataBlob_inherits_ReportData
/// <summary>
/// Parent (One-to-One) ReportData pointed by [ReportDatas_LogData].[Id] (FK_LogData_inherits_ReportData)
/// </summary>
public virtual LogData LogData { get; set; } // ReportDatas_LogData.FK_LogData_inherits_ReportData
/// <summary>
/// Child Tags (Many-to-Many) mapped by table [ReportDataTag]
/// </summary>
public virtual ObservableCollection<Tag> Tags { get; set; } // Many to many mapping
/// <summary>
/// Parent (One-to-One) ReportData pointed by [ReportDatas_ReturnData].[Id] (FK_ReturnData_inherits_ReportData)
/// </summary>
public virtual ReturnData ReturnData { get; set; } // ReportDatas_ReturnData.FK_ReturnData_inherits_ReportData
// Foreign keys
/// <summary>
/// Parent TestStep pointed by [ReportDatas].([TestStep_Id]) (TestStepReportData)
/// </summary>
public virtual TestStep TestStep { get; set; } // TestStepReportData
public ReportData()
{
Tags = new ObservableCollection<Tag>();
InitializePartial();
}
partial void InitializePartial();
}
`2: ReturnData
[GeneratedCode("EF.Reverse.POCO.Generator", "v3.1.3")]
// ReportDatas_ReturnData
public partial class ReturnData : ReportData
{
public bool Valid { get; set; } // Valid
public TestStatus Status { get; set; } // Status
public string Comment { get; set; } // Comment
// Reverse navigation
/// <summary>
/// Parent (One-to-One) ReturnData pointed by [ReportDatas_DataHeader].[Id] (FK_DataHeader_inherits_ReturnData)
/// </summary>
public virtual DataHeader DataHeader { get; set; } // ReportDatas_DataHeader.FK_DataHeader_inherits_ReturnData
/// <summary>
/// Parent (One-to-One) ReturnData pointed by [ReportDatas_DataValue].[Id] (FK_DataValue_inherits_ReturnData)
/// </summary>
public virtual DataValue DataValue { get; set; } // ReportDatas_DataValue.FK_DataValue_inherits_ReturnData
/// <summary>
/// Parent (One-to-One) ReturnData pointed by [ReportDatas_NumberValue].[Id] (FK_NumberValue_inherits_ReturnData)
/// </summary>
public virtual NumberValue NumberValue { get; set; } // ReportDatas_NumberValue.FK_NumberValue_inherits_ReturnData
/// <summary>
/// Parent (One-to-One) ReturnData pointed by [ReportDatas_TextValue].[Id] (FK_TextValue_inherits_ReturnData)
/// </summary>
public virtual TextValue TextValue { get; set; } // ReportDatas_TextValue.FK_TextValue_inherits_ReturnData
// Foreign keys
/// <summary>
/// Parent ReportData pointed by [ReportDatas_ReturnData].([Id]) (FK_ReturnData_inherits_ReportData)
/// </summary>
public virtual ReportData ReportData { get; set; } // FK_ReturnData_inherits_ReportData
public ReturnData()
{
InitializePartial();
}
partial void InitializePartial();
}
3: значение данных.
[GeneratedCode("EF.Reverse.POCO.Generator", "v3.1.3")]
// ReportDatas_DataValue
public partial class DataValue : ReturnData
{
public byte[] Data { get; set; } // Data
// Reverse navigation
/// <summary>
/// Parent (One-to-One) DataValue pointed by [ReportDatas_CompareDataValue].[Id] (FK_CompareDataValue_inherits_DataValue)
/// </summary>
public virtual CompareDataValue CompareDataValue { get; set; } // ReportDatas_CompareDataValue.FK_CompareDataValue_inherits_DataValue
// Foreign keys
/// <summary>
/// Parent ReturnData pointed by [ReportDatas_DataValue].([Id]) (FK_DataValue_inherits_ReturnData)
/// </summary>
This line is commented out by me. If I leave this in, it’s hiding the ReturnData which is already present in the base class. This might be part of the issue.
// public virtual ReturnData ReturnData { get; set; } // FK_DataValue_inherits_ReturnData
public DataValue()
{
InitializePartial();
}
partial void InitializePartial();
}
4: CompareDataValue
[GeneratedCode("EF.Reverse.POCO.Generator", "v3.1.3")]
// ReportDatas_CompareDataValue
public partial class CompareDataValue : DataValue
{
public byte[] CompareData { get; set; } // CompareData
public DataCompareType CompareType { get; set; } // CompareType
// Foreign keys
/// <summary>
/// Parent DataValue pointed by [ReportDatas_CompareDataValue].([Id]) (FK_CompareDataValue_inherits_DataValue)
/// </summary>
This line is commented out by me. If I leave this in, it’s hiding the ReturnData which is already present in the base class. This might be part of the issue.
//public virtual DataValue DataValue { get; set; } // FK_CompareDataValue_inherits_DataValue
public CompareDataValue()
{
InitializePartial();
}
partial void InitializePartial();
}
Сгенерированные классы конфигурации.
1: ReportDataConfiguration:
[GeneratedCode("EF.Reverse.POCO.Generator", "v3.1.3")]
// ReportDatas
public partial class ReportDataConfiguration : EntityTypeConfiguration<ReportData>
{
public ReportDataConfiguration()
: this("dbo")
{
}
public ReportDataConfiguration(string schema)
{
ToTable("ReportDatas", schema);
HasKey(x => x.Id);
Property(x => x.Id).HasColumnName(@"Id").HasColumnType("int").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
Property(x => x.Timestamp).HasColumnName(@"Timestamp").HasColumnType("datetime").IsRequired();
Property(x => x.TestStep_Id).HasColumnName(@"TestStep_Id").HasColumnType("int").IsRequired();
// Foreign keys
HasRequired(a => a.TestStep).WithMany(b => b.ReportDatas).HasForeignKey(c => c.TestStep_Id).WillCascadeOnDelete(false); // TestStepReportData
HasMany(t => t.Tags).WithMany(t => t.ReportDatas).Map(m =>
{
m.ToTable("ReportDataTag", "dbo");
m.MapLeftKey("ReportDataTag_Tag_Id");
m.MapRightKey("Tags_Id");
});
InitializePartial();
}
partial void InitializePartial();
}
2: ReturnDataConfiguration:
[GeneratedCode("EF.Reverse.POCO.Generator", "v3.1.3")]
// ReportDatas_ReturnData
public partial class ReturnDataConfiguration : EntityTypeConfiguration<ReturnData>
{
public ReturnDataConfiguration()
: this("dbo")
{
}
public ReturnDataConfiguration(string schema)
{
ToTable("ReportDatas_ReturnData", schema);
This line is commented out by me as the POCO also does not have this.
//HasKey(x => x.Id);
Property(x => x.Valid).HasColumnName(@"Valid").HasColumnType("bit").IsRequired();
Property(x => x.Status).HasColumnName(@"Status").HasColumnType("tinyint").IsRequired();
Property(x => x.Comment).HasColumnName(@"Comment").HasColumnType("nvarchar(max)").IsRequired();
This line is commented out by me as the POCO also does not have this.
If I leave these in, I can’t even create a context.
//Property(x => x.Id).HasColumnName(@"Id").HasColumnType("int").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
// Foreign keys
HasRequired(a => a.ReportData).WithOptional(b => b.ReturnData); // FK_ReturnData_inherits_ReportData
InitializePartial();
}
partial void InitializePartial();
}
3: DataValueConfiguration
[GeneratedCode("EF.Reverse.POCO.Generator", "v3.1.3")]
// ReportDatas_DataValue
public partial class DataValueConfiguration : EntityTypeConfiguration<DataValue>
{
public DataValueConfiguration()
: this("dbo")
{
}
public DataValueConfiguration(string schema)
{
ToTable("ReportDatas_DataValue", schema);
//HasKey(x => x.Id);
Property(x => x.Data).HasColumnName(@"Data").HasColumnType("varbinary(max)").IsRequired();
This line is commented out by me as the POCO also does not have this.
If I leave these in, I can’t even create a context.
//Property(x => x.Id).HasColumnName(@"Id").HasColumnType("int").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
// Foreign keys
HasRequired(a => a.ReturnData).WithOptional(b => b.DataValue).Map(k=>k.MapKey("Id")); // FK_DataValue_inherits_ReturnData
InitializePartial();
}
partial void InitializePartial();
}
4: CompareDataValueConfiguration
[GeneratedCode("EF.Reverse.POCO.Generator", "v3.1.3")]
// ReportDatas_CompareDataValue
public partial class CompareDataValueConfiguration : EntityTypeConfiguration<CompareDataValue>
{
public CompareDataValueConfiguration()
: this("dbo")
{
}
public CompareDataValueConfiguration(string schema)
{
ToTable("ReportDatas_CompareDataValue", schema);
//HasKey(x => x.Id);
Property(x => x.CompareData).HasColumnName(@"CompareData").HasColumnType("varbinary(max)").IsRequired();
Property(x => x.CompareType).HasColumnName(@"CompareType").HasColumnType("tinyint").IsRequired();
This line is commented out by me as the POCO also does not have this.
If I leave these in, I can’t even create a context.
//Property(x => x.Id).HasColumnName(@"Id").HasColumnType("int").IsRequired().HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
// Foreign keys
HasRequired(a => a.DataValue).WithOptional(b => b.CompareDataValue).Map(k => k.MapKey("Id")); // FK_CompareDataValue_inherits_DataValue
InitializePartial();
}
partial void InitializePartial();
}
Мои вопросы:
Какой лучший способ исправить это?
Я мог бы изменить имена таблиц в соответствии со стандартными соглашениями CF. Как тогда должны быть названы столбцы? Следует избегать обновления классов POCO.
Обновление конфигурации, чтобы FK были найдены? Как это сделать?
Другие варианты / предложения?
Я уже читал и выполнял поиск по стеку и попробовал несколько попыток, но не могу его найти. Также следовал курсам от Jul ie Лермана по Pluralsight.
Мне было странно, что даже генератор ReversePoco от Simon пришлось адаптировать для работы с этим типом наследования классов. У нас с Саймоном было много рассылок, чтобы выяснить проблему. Тот факт, что генератор для такой маленькой базы данных и с простыми отношениями позволяет мне думать, что что-то не так в этой БД и как создаются классы.
Любые комментарии и предложения по этому поводу приветствуются! С уважением, Брэм