Entity Framework-Validierung mit teilweise Aktualisierungen
Bin ich mit Entity Framework 5.0 mit DbContext-und POCO-Entitäten. Es gibt eine einfache Einheit mit 3 Eigenschaften:
public class Record
{
public int Id { get; set; }
public string Title { get; set; }
public bool IsActive { get; set; }
}
Dem Titel-Feld ist immer unverändert, und die UI zeigt einfach, ohne jedes Eingabefeld, um es zu ändern. Das ist, warum die Title
Feld null
wenn das Formular an den server gesendet wird.
Hier ist, wie ich sage EF zu führen partielles update des Unternehmens (IsActive
Feld nur):
public class EFRepository<TEntity>
{
...
public void PartialUpdate(TEntity entity, params Expression<Func<TEntity, object>>[] propsToUpdate)
{
dbSet.Attach(entity);
var entry = _dbContext.Entry(entity);
foreach(var prop in propsToUpdate)
contextEntry.Property(prop).IsModified = true;
}
}
und der Ruf:
repository.PartialUpdate(updatedRecord, r => r.IsActive);
Aufrufen SaveChanges
Methode, bekomme ich die DbEntityValidationException
, das mir sagt, Title
erforderlich ist. Wenn ich dbContext.Configuration.ValidateOnSaveEnabled = false
ist alles OK.
Gibt es eine Möglichkeit, vermeiden Sie das deaktivieren der überprüfung auf den gesamten Kontext und zu sagen, das EF nicht die Eigenschaften überprüft werden, die nicht aktualisiert wird?
Vielen Dank im Voraus.
- Dies scheint wie eine Menge Arbeit, um etwas zu tun, das ist ganz einfach, befassen sich mit sonst. Sie gehören einfach einem versteckten Feld im Formular mit Ihrer read-only-Modell Elemente, dann sind Sie in dem update enthalten und EF macht seinen ändern, tracking-und kennt den Wert nicht geändert hat.
- Was ist stub Personen als? Zum Beispiel, ich hab eine Action-Methode, die Sie markiert eine Person, die als gelöscht. Die folgenden code:
var person = new Person { Id = 5 }; dbSet.Attach(person); dbSet.Entry(person).Property(p => p.IsDeleted).IsModified = true; dbContext.SaveChanges();
wird die Ursache die gleiche Ausnahme. Tut DbContext Validierung der Arbeit gut mit stub-Entitäten überhaupt? Ich möchte aviod abrufen der gesamten Entität aus der Datenbank nur für die Markierung als gelöscht. - Funktioniert es wirklich? Befestigen Sie wird verwendet, wenn Sie eine Entität in der hand und Sie sind sicher, dass diese Entität in der Datenbank existiert und ist identisch. Ordnen Sie eine Person, die sich von dem unterscheidet, was in der Filiale (der Titel ist anders). Dann Kennzeichnen Sie die entity als geändert (durch Markierung einer Eigenschaft geändert werden kann). Da EF arbeitet auf Personen und nicht auf Eigenschaften, die es aktualisieren wird, alle Eigenschaften und nicht nur die, die als geändert markiert. Mein mentales Modell von der EF sagt mir, dass der Title-Spalte in der Datenbank auf null gesetzt werden nach diesem. Können Sie überprüfen, wenn dies nicht der Fall ist?
- Validierung standardmäßig überprüft, die alle Eigenschaften von Entitäten in der Zusätzlichen und Geänderten Zustand. Es ist möglich, dieses Verhalten zu ändern durch die Verwendung von Erweiterungsmechanismen ausgesetzt durch die Validierung. Beachten Sie, dass sobald Sie markieren Sie Ihr angeschlossenen Unternehmen als geändert es ist nicht mehr ein stub-Einrichtung, wie ich glaube, es wird an die Datenbank geschickt werden...
- EF ermöglicht partielle updates der Einheit. Zum Beispiel
dbSet.Attach(entity); dbContext.Entry(entity).State = EntityState.Modified; dbContext.SaveChanges();
update wird die gesamte Einheit. Wenn Sie sagen, dass EF explizit, welche Eigenschaften zu aktualisieren, nur sind diese Eigenschaften aktualisiert.dbSet.Attach(entity); dbContext.Entry(entity).Property(e => e.Title).IsModified = true; dbContext.SaveChanges();
update nur Titel. Mit deaktiviert die Validierung, das funktioniert gut. - Mit diesem Ansatz(explizit sagen, EF, welche Eigenschaften zu aktualisieren) auch kann ich update eine andere Eigenschaft
(entity.IsActive = false)
, aber bisher habe ich nicht markieren Sie ihn als aktualisiert(e => e.IsActive).IsModified = true;
es wird nicht aktualisiert.entity.State = EntityState.Modified
markiert die gesamte Einheit als sofort aktualisiert. - Sie müssen nicht zum abrufen der Entität zu markieren als gelöscht, nur ein einfaches SQL-Anweisung mit
dbSet.SqlCommand("UPDATE entity SET deleted = true where x = y")
, das ist VIEL einfacher als der Weg, den Sie nehmen. - Ich denke du bist über-engineering eine Lösung. Es darf heute arbeiten, aber AFAIK ist dies keine unterstützte Möglichkeit, dies zu tun, was bedeutet, es kann brechen in einer zukünftigen version. Die Tatsache, dass Sie die Probleme sollten Ihnen sagen, dass es nicht, in der Tat, tatsächlich funktioniert. Stub-Entitäten werden unterstützt, aber Sie können nur der Schlüssel-Wert wird unterstützt. Wenn Sie mehr als nur die Schlüssel, es ist kein stub mehr.
- BTW, stub-Einheiten sind nicht mehr die bevorzugte Methode, eher die FK Vereine sind. Und Sie sind leistungsfähiger.
- Glaube nicht, über die raw-sql 🙂 vielen Dank für Eure Antworten, Jungs
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie partielle updates oder stub-Entitäten (beide Ansätze sind ziemlich gültig!) Sie können die Globale EF-Validierung, weil es nicht respektieren Ihre teilweise änderungen - es überprüft die gesamte Einheit. Mit Standard-Validierungs-Logik müssen Sie es deaktivieren, indem Sie den Aufruf erwähnt:
Validieren und jeder aktualisierte Eigentum getrennt. Dies sollte hoffentlich machen die Magie, aber ich versuchte es nicht, weil ich nicht verwenden, EF-Validierung an alle:
Wenn Sie möchten, gehen Sie Schritt weiter, können Sie versuchen, überschreiben
ValidateEntity
in Ihrem Kontext und implementieren Validierung in der Weise, dass es überprüft die gesamte Einheit oder nur ausgewählte Eigenschaften, basierend auf den Zustand der Entität undIsModified
Zustand der Eigenschaften, die Ihnen erlauben, mit EF-Validierung mit partiellen updates und stub-Entitäten.Validierung in EF ist IMHO falsch Konzept - es führt auch zusätzliche Logik in den data-access-layer, wo die Logik nicht gehört. Es basiert hauptsächlich auf der Idee, dass Sie arbeiten immer mit der ganzen Person oder sogar mit ganzen entity-Diagramm, wenn Sie legen Sie die erforderlichen Validierung Regeln, die auf der Navigations-Eigenschaften. Sobald Sie gegen diese Vorgehen, Sie werden immer finden, dass die einzigen festen set von Prüfregeln fest auf Ihre Entitäten nicht ausreichend.
Eines der Dinge, die ich in meinem sehr langen Rückstau ist es zu untersuchen, wie die Validierung betrifft die Geschwindigkeit der
SaveChanges
Betrieb - früher habe ich meine eigenen validation-API in EF4 (vor EF4.1) basierend auf DataAnnotations und IhreValidator
Klasse und ich habe aufgehört, Sie Recht bald durch eine sehr schlechte Leistung.Workaround mittels native SQL hat die gleichen Auswirkungen wie die Verwendung von stub-Entitäten oder teilweise mit updates ausgeschaltet validation = Ihre Einheiten sind noch nicht validiert, aber neben deinen änderungen sind nicht Teil der gleichen Einheit arbeiten.
IsModified
nur.In Bezug auf Ladislav Antwort, ich habe dies nur Hinzugefügt, um die
DbContext
Klasse, und er entfernt nun alle die Eigenschaften, die nicht verändert werden.Ich weiß, das ist nicht ganz überspringen der Validierung für die Eigenschaften, sondern nur weglassen, aber EF überprüft, pro Person, die nicht Eigentum, und das umschreiben der gesamten Validierungsprozess von neuem, es war zu viel Aufwand für mich.
if (entityEntry.State != EntityState.Modified) return false;
innerhalb derWhere
, um sicher zu sein, entfernen Sie die falseErrors nur beim aktualisieren der Person, da sonst bei der addition der Validierung werden alle entfernt, nur weil die FlaggeIsModified
ist nicht festgelegt.if (entityEntry.State == EntityState.Modified)
einwickeln dervar falseErrors
und dieforeach
um zu verhindern, dass das Verhalten Michael Denny beschrieben. Besser als es in der Linq-Anfrage.Dies ist ein remix von früheren @Shimmy Antwort und es ist eine version, die ich derzeit verwenden.
Was ich Hinzugefügt habe, ist die Klausel
(entityEntry.State != EntityState.Modified) return false;
imWhere
: