Ich habe drei Tabellen;
- ist eine Kurzreferenz. Es enthält nur die neueste Version jedes Objekts und nicht alle Felder. Es ist mit der ObjectId verknüpft (verfügt aber auch über eine VersionId, die jedes Mal aktiviert wird, wenn ein Objekt gespeichert wird)
Code: Select all
Current - ist ein Verlauf von Current. Es hat genau die gleichen Felder wie Current, aber hier ist VersionId im Schlüssel enthalten. Es ist also auf ObjectId + VersionId
Code: Select all
Archive - kodiertenthält einen XML-Blob mit feldweisen Änderungen an den Objekten. Es verfügt über eine vollständige Liste der Felder, die zwischen zwei Versionen eines Objekts geändert wurden, gespeichert als „Feldname“, „alter Wert“, „neuer Wert“.
Code: Select all
Change
Es verfügt über eine ObjectId-Spalte, aber Sie müssen das XML analysieren, um die beteiligten VersionIds zu erhalten (in der Form „alter Wert“, „neuer Wert“).
In SQL ausgedrückt wäre der Code zum Auffüllen jeder dieser Beziehungen:
Code: Select all
'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 =
Code: Select all
[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; }
}
Code: Select all
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...
Ist das in EF 6 überhaupt möglich? Wenn nicht, haben Sie irgendwelche Vorschläge, wie man es anders machen kann, ohne den Rest des EF 6-Datenabrufs völlig zu beeinträchtigen?
Die Beziehungen sind nicht wirklich so verrückt, daher wäre es schön, wenn es möglich wäre.
Ich habe einigen Einfluss auf die Datenbank, aber er ist größtenteils gegeben.
Ich habe viel mehr Einfluss auf den C#-Code, kann dort aber auch keine allzu verrückten Dinge tun – wie zum Beispiel die Migration zu einem anderen ORM …
BEARBEITEN: Einige der Konfigurationen, die ich ausprobiert habe, und ihre SQL-Fehler
Code: Select all
modelBuilder.Entity()
.HasMany(arch => arch.Changes)
.WithMany();
Code: Select all
modelBuilder.Entity()
.HasMany(arch => arch.Changes)
.WithMany(chg => chg.Archive);
Code: Select all
modelBuilder.Entity()
.HasMany(chg => chg.ArchivedObjects)
.WithMany();
Code: Select all
modelBuilder.Entity()
.HasMany(chg => chg.ArchivedObjects)
.WithMany(arch => arch.Changes);
Mobile version