У меня есть три таблицы;
- — это краткий справочник. Он содержит только последнюю версию каждого объекта, а не все поля. Он привязан к ObjectId (но также имеет VersionId, который увеличивается при каждом сохранении объекта)
Код: Выделить всё
Current - — это история текущего. Он имеет точно такие же поля, что и Current, но здесь в ключ включен VersionId. Таким образом, он привязан к ObjectId + VersionId
Код: Выделить всё
Archive - содержит большой двоичный объект XML с полевыми изменениями объектов. Он содержит полный список полей, измененных между двумя версиями объекта, которые хранятся как «имя поля», «старое значение», «новое значение».
Код: Выделить всё
Change
У него есть столбец ObjectId, но вам необходимо проанализировать XML, чтобы получить задействованные значения VersionId (находятся в форме «старое значение», «новое значение»)
В терминах SQL код для заполнения каждого из этих отношений будет выглядеть так:
Код: Выделить всё
'Current.Changes' => SELECT * FROM Change WHERE ObjectId =
'Archive.Changes' => SELECT * FROM Change WHERE ObjectId =
'Change.Current' => SELECT * FROM Current WHERE ObjectId =
'Change.ArchivedObjects' => SELECT * FROM Archive WHERE ObjectId =
Код: Выделить всё
[Table(nameof(Current))]
public class Current : ITrObject // = common interface for 'Current' and 'Archive'
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ObjectId { get; set; }
public int VersionId { get; set; }
// ... Lots of properties ...
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection Changes { get; set; }
}
[Table(nameof(Archive))]
public class Archive : ITrObject
{
[Key, Column(Order = 0), DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ObjectId { get; set; }
[Key, Column(Order = 1), DatabaseGenerated(DatabaseGeneratedOption.None)]
public int VersionId { get; set; }
// ... Lots of properties ...
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection Changes { get; set; }
}
[Table(nameof(Change))]
public class Change
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public int ChangeId { get; set; }
public int? ObjectId { get; set; } // 'int?' because the source system sometimes creates changes that are logged, but not saved yet. Probably some kind of 'autosave' feature.
// ... Lots of properties ...
[ForeignKey(nameof(ObjectId))]
public virtual Current Current { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection ArchivedObjects { get; set; }
}
Код: Выделить всё
modelBuilder.Entity()
.HasMany(cur => cur.Changes)
.WithOptional(chg => chg.Current)
.HasForeignKey(chg => chg.ObjectId)
.WillCascadeOnDelete(false);
modelBuilder.Entity()
.HasMany(arch => arch.Changes)
.WithMany(); // Stuck here...
Возможно ли это вообще в EF 6? Если нет, есть ли у вас какие-либо предложения о том, как сделать это каким-либо другим способом, который не будет полностью портить остальную часть извлечения данных EF 6?
Отношения на самом деле не такие уж сумасшедшие, поэтому было бы неплохо, если бы это можно было сделать.
Я имею некоторое влияние на базу данных, но в основном оно предоставлено.
Я имею гораздо больше влияния на нее код C#, но и там я не могу делать слишком сумасшедшие вещи - например, переход на другой ORM...
РЕДАКТИРОВАТЬ: некоторые из конфигураций, которые я пробовал, и их ошибки SQL
Код: Выделить всё
modelBuilder.Entity()
.HasMany(arch => arch.Changes)
.WithMany();
Код: Выделить всё
modelBuilder.Entity()
.HasMany(arch => arch.Changes)
.WithMany(chg => chg.Archive);
Код: Выделить всё
modelBuilder.Entity()
.HasMany(chg => chg.ArchivedObjects)
.WithMany();
Код: Выделить всё
modelBuilder.Entity()
.HasMany(chg => chg.ArchivedObjects)
.WithMany(arch => arch.Changes);
Подробнее здесь: https://stackoverflow.com/questions/797 ... e-property
Мобильная версия