Hallo Community,
es ist mir echt peinlich, aber ich kriege das folgende Problem,
ein simples CascadeOnDelete im EntityFramework (CodeFirst)
einfach nicht gelöst:
Diese abstrakte Basisklasse wird an alle relevanten Entities der Anwendung vererbt. Sie beinhaltet die ID jedes Objektes.
In der Datenbank erscheint damit in jeder Tabelle eine Id(PK,FK, uniqueidentifier, notNull) und in der Tabelle MetaData eine Zeile für jede
Entity, egal welcher abgeleiteter Klasse. MetaData speichert diverse Indikatoren, ob ein Objekt gerade editiert wird,
wann und von wem es zuletzt gepeichert wurde, usw. um die Zugriffsprobleme im MultiUser-Betrieb zumindest halbwegs in den Griff zu kriegen.
[Table("MetaData")]
[Serializable]
public abstract class MetaData : INotifyPropertyChanged
{
[Key]
public Guid Id { get; set; }
....
}
Das Scenario, um das es geht ist folgendes:
[Table("CompanySites")]
[Serializable]
public class CompanySite : MetaData
{
...
private ObservableCollection<CompanySiteRoleType> _companySiteRoleTypes;
public virtual ObservableCollection<CompanySiteRoleType> CompanySiteRoleTypes
{
get
{
return _companySiteRoleTypes;
}
set
{
if (_companySiteRoleTypes != value)
{
_companySiteRoleTypes = value;
SetPropertyChanged();
}
}
}
...
}//public class CompanySite : MetaData
[Table("CompanySiteRoleTypes")]
[Serializable]
public class CompanySiteRoleType : MetaData
{
...
public Guid CompanySiteId { get; set; }
private CompanySite _companySite;
[ForeignKey("CompanySiteId")]
[Index("CompanySiteIdAndCompanyRoleType", 1)]
public virtual CompanySite CompanySite
{
get
{
return _companySite;
}
set
{
if (_companySite != value)
{
_companySite = value;
SetPropertyChanged();
}
}
}
...
}//public class CompanySiteRoleType : MetaData
Was ich will ist, dass wenn ein Objekt vom Typ CompanySite gelöscht wird, alle dieser Instanz über die ObservableBindingCollection
zugeordneten Objekte vom Typ CompanySiteRoleType ebenfalls gelöscht werden.
Wenn ich mich so umsehe, sollte dieses Verhalten wohl eigentlich sogar standardmäßig so sein.
Aber leider Fehlanzeige. Im SQL-Studio sehe ich den ForeignKey in den CompanySiteRoleTypes korrekt abgebildet, aber die DeleteRule ist immer "NoAction".
Auch wenn ich im modelBuilder folgende Zeile angebe, ändert dies leider nichts:
modelBuilder.Entity<CompanySite>().HasMany(i => i.CompanySiteRoleTypes).WithRequired(i => i.CompanySite).WillCascadeOnDelete(true);
Nun meine Frage: Kann es sein, dass die Basisfunktionalität "CascadeOnDelete" durch meine Konstruktion mit der abstakten Basisklasse "MetaData" ausgehebelt wird?
Ich weiß, dass man das alles alles auch "händisch" durch Iteration durch die Liste und manuelles Löschen der betroffenen Entities erreichen kann,
aber ich kann und will nicht glauben, dass es für dieses banale Problem, das vermutlich zigfach in jeder Datenbankanwendung erforderlich ist,
keine andere Lösung gibt.
Viele Grüße und vielen Dank Euch !!
Christoph
Die Models für den EF sollten reine "POCOs" (Plain old CLR objects) sein, also keinerlei Logik (wie z.B. INotifyPropertyChange) enthalten. Die Logik gehört in die BL, und die Logik der Benutzeroberfläche in ein ViewModel o.ä.
Weeks of programming can save you hours of planning
.. und verzichte auf die Attribute in EF und verwende Fluent Code für die Modellierung.
Von einem Mix, wie Du es hast, wird ausdrücklich abgeraten.
Zum Trennung von Klassen:
[Artikel] Drei-Schichten-Architektur
- performance is a feature -
Microsoft MVP - @Website - @AzureStuttgart - github.com/BenjaminAbt - Sustainable Code
Hallo Abt, hallo MrSparkle,
vielen Dank für Eure Antworten.
Ich ziehe daraus den folgenden Schluß:
Prinzipiell steht das Konstrukt mit der abgeleiteten Basisklasse
nicht im Widerspruch zu CascadeOnDelete.
Ich habe nur ein paar Dinge falsch angepackt.
Ich werde nun versuchen, die von Euch vorgeschlagene Trennung
zwischen Modellierung und Daten umzusetzen.
Vielen Dank nochmals und viele Grüße
Christoph