Es ist eine perfekte Art und Weise dieser 4.0 in EF zu erreichen, indem ObjectStateManager
Zuerst nutzen, benötigen Sie eine partielle Klasse für Ihre Object erstellen und abonnieren zu ObjectContext.SavingChanges Event. Der beste Ort für dieses Ereignis ist die OnContextCreated-Methode. Diese Methode wird von dem Kontextobjekt Konstruktor und den Konstruktorüberladungen genannt, die eine partielle Methode ohne Implementierung ist:
partial void OnContextCreated() {
this.SavingChanges += Context_SavingChanges;
}
nun der eigentliche Code, der die Arbeit erledigt:
void Context_SavingChanges(object sender, EventArgs e) {
IEnumerable<ObjectStateEntry> objectStateEntries =
from ose
in this.ObjectStateManager.GetObjectStateEntries(EntityState.Added
| EntityState.Modified)
where ose.Entity != null
select ose;
foreach (ObjectStateEntry entry in objectStateEntries) {
ReadOnlyCollection<FieldMetadata> fieldsMetaData = entry.CurrentValues
.DataRecordInfo.FieldMetadata;
FieldMetadata modifiedField = fieldsMetaData
.Where(f => f.FieldType.Name == "LastModifiedUser").FirstOrDefault();
if (modifiedField.FieldType != null) {
string fieldTypeName = modifiedField.FieldType.TypeUsage.EdmType.Name;
if (fieldTypeName == PrimitiveTypeKind.String.ToString()) {
entry.CurrentValues.SetString(modifiedField.Ordinal, Lookupuser());
}
}
}
}
-Code Erläuterung:
Dieser Code sucht nach Hinzugefügt oder Geändert Einträge, die eine LastModifiedUser -Eigenschaft haben, und aktualisiert diese Eigenschaft mit dem Wert, der von Ihrer benutzerdefinierten Lookupuser() Methode stammt.
In dem Foreach-Block bohrt die Abfrage grundsätzlich in die CurrentValues jedes Eintrags. Dann die Wo Methode verwendet, sieht es an den Namen jedes FieldMetaData Artikel für diesen Eintrag, nur die Aufnahme von deren Name ist LastModifiedUser. Als Nächstes überprüft die if-Anweisung, dass die Eigenschaft LastModifiedUser ein String Feld ist; dann aktualisiert es den Wert des Feldes.
Ein anderer Weg, um dieses Verfahren zum Anschließen (statt zu Saving Ereignis abonnieren) durch die ObjectContext.SaveChanges Method überschreiben.
By the way, gehört der obige Code zu Julie Lerman von ihrem Programming Entity Framework Buch.
EDIT für Self-Tracking POCO Implementierung:
Wenn Sie selbst Tracking POCOs haben dann, was ich tun würde, ist, dass ich zuerst die T4-Vorlage ändern, um die OnContextCreated() -Methode aufrufen. Wenn Sie Ihre ObjectContext.tt Datei betrachten, gibt es eine Initialize() Methode, die von allen Konstruktoren aufgerufen wird, also ein guter Kandidat, um unsere OnContextCreated() -Methode aufzurufen, also müssen wir nur ObjectContext.tt ändern Datei wie folgt:
private void Initialize()
{
// Creating proxies requires the use of the ProxyDataContractResolver and
// may allow lazy loading which can expand the loaded graph during serialization.
ContextOptions.ProxyCreationEnabled = false;
ObjectMaterialized += new ObjectMaterializedEventHandler(HandleObjectMaterialized);
// We call our custom method here:
OnContextCreated();
}
Und dies wird dazu führen, dass unsere OnContextCreated() beim Erstellen des Kontexts aufgerufen wird.
Nun, wenn Sie Ihre POCOs hinter der Dienstgrenze setzen, dann bedeutet es, dass der ModifiedUserName mit dem Rest der Daten von Ihren WCF-Service-Consumer kommen muß. Sie können entweder diese LastModifiedUser Eigenschaft, um sie aussetzen zu aktualisieren, oder wenn es in einer anderen Eigenschaft speichert, und Sie wünschen LastModifiedUser von dieser Eigenschaft aktualisieren, dann können Sie den zweiten Code wie folgt ändern:
foreach (ObjectStateEntry entry in objectStateEntries) {
ReadOnlyCollection fieldsMetaData = entry.CurrentValues
.DataRecordInfo.FieldMetadata;
FieldMetadata sourceField = fieldsMetaData
.Where(f => f.FieldType.Name == "YourPropertyName").FirstOrDefault();
FieldMetadata modifiedField = fieldsMetaData
.Where(f => f.FieldType.Name == "LastModifiedUser").FirstOrDefault();
if (modifiedField.FieldType != null) {
string fieldTypeName = modifiedField.FieldType.TypeUsage.EdmType.Name;
if (fieldTypeName == PrimitiveTypeKind.String.ToString()) {
entry.CurrentValues.SetString(modifiedField.Ordinal,
entry.CurrentValues[sourceField.Ordinal].ToString());
}
}
}
Hoffe, das hilft.
Danke für die Antwort. Ich hatte mir dieses Muster vorher angeschaut, konnte aber das onContextCreated-Ereignis nie auslösen. – Biggle10
Kein Problem. Wie gesagt, OnContextCreated ist kein Event, sondern nur eine partielle Methode ohne Implementierung, die vom Konstruktor des Context-Objekts und den Überladungen des Konstruktors aufgerufen wird. Alles, was Sie tun müssen, ist eine Teilklasse für Ihren Kontext zu erstellen und mein erstes Code-Snippet einzufügen. Bitte tun Sie dies und lassen Sie mich wissen, wie es für Sie funktioniert, und wenn es immer noch nicht funktioniert, werden wir es schaffen! –
Eigentlich habe ich darüber nachgedacht und falsch beschrieben. Lassen Sie mich meine Frage präzisieren ... Wir verwenden Self-Trackign-Entitäten und sie werden über einen WCF-Service an das Frontend bereitgestellt. Wenn sie zurückgegeben werden, werden wir erneut an den Kontext gebunden und speichern. Wenn sie im Besitz des Clients geändert wurden, muss der lastModifiedUser dies widerspiegeln. Der Server hat keinen Zugriff darauf, wer der aktuelle Benutzer ist, daher kann er nicht derjenige sein, der für die Einstellung des Benutzers verantwortlich ist. Ich nehme theoretisch an, dass ich etwas wie eine oncreated-Ereignis-/Partial-Methode auf Entitätsebene machen möchte? – Biggle10