Entity Framework-Satz-navigation-Eigenschaft auf null
Ich habe einen entity framework-database first-Projekt. hier ist eine Extraktion des Modells:
public partial class LedProject
{
public LedProject()
{
this.References = new HashSet<LedProjectReference>();
this.Results = new HashSet<LedProjectResult>();
this.History = new HashSet<LedProjectHistory>();
}
public string Identifier { get; set; }
public string Name { get; set; }
public Nullable<System.DateTime> CompletionDate { get; set; }
public System.DateTime CreationDate { get; set; }
public System.Guid ProjectId { get; set; }
public string Comment { get; set; }
public virtual User ContactUser { get; set; }
public virtual User CreationUser { get; set; }
public virtual Customer Customer { get; set; }
public virtual LedProjectAccounting Accounting { get; set; }
public virtual LedProjectState State { get; set; }
public virtual ICollection<LedProjectReference> References { get; set; }
public virtual ICollection<LedProjectResult> Results { get; set; }
public virtual User ResponsibleUser { get; set; }
public virtual ICollection<LedProjectHistory> History { get; set; }
}
public partial class User
{
public System.Guid UserId { get; set; }
public string LoginName { get; set; }
public System.DateTime CreationDate { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public string Email { get; set; }
}
Ich habe ein problem mit der Einstellung der navigation den Punkt ResponsibleUser
von der Klasse LedProject
. Wenn ich die ResponsibleUser
zu einem anderen Benutzer, und danach speichern Sie die änderungen der DBContext, die änderungen werden in der Datenbank gespeichert.
Aber, wenn ich will, löschen Sie den aktuellen ResponsibleUser
einer LedProject
durch Einstellung der Navigations-Eigenschaft auf null. Die änderungen werden nicht in der Datenbank gespeichert.
LedProject project = db.LedProject.Find(projectId);
project.Name = string.IsNullOrEmpty(name) ? null : name;
...
project.ResponsibleUser = responsibleUser == null ? null : db.User.Find(responsibleUser.UserId);
...
db.SaveChanges();
Gibt es irgendeinen trick für das löschen von Navigations-Eigenschaften?
- Sind Sie sicher, dass
responsibleUser
ist eigentlich null, wenn Sie die Einstellungproject.ResponsibleUser
? Die Erklärung, die ist nicht hier. Tut es klar, die navigation, wenn Sie ersetzen, dass Sie die ganze Zeile mitproject.ResponsibleUser = null;
? - es immer noch nicht die Eigenschaft löschen, wenn ich die Zeile ändern zu Projekt.ResponsibleUser = null; Im debug-Modus sehe ich, dass die Eigenschaft auf null gesetzt, aber es wird nicht gespeichert, indem Sie die Methode SaveChanges()
- Ist die Datenbank, die Spalte null-Werte zulässt? Ist das mapping für die Spalte ID gesetzt, um null-Werte zulassen? Ich habe in der Regel gesehen deklarierten Eigenschaften wie
Nullable<User>
wenn der Wert null ist eigentlich ein legitimer Wert für Sie. Aber ich habe nicht viel arbeiten EF Praxis, so dass, wenn das ist es nicht, ich bin aus Ideen heraus. - Die Datenbank-Spalte null-Werte zulässt. Es ist schon möglich, speichern einen null-Wert in dieser Eigenschaft, weil ich eine neue LedProject ohne ResponibleUser.
- Ich bin aus Ideen heraus, dann. Viel Glück.
- Scheint ein wenig seltsam. Was passiert, wenn Sie
project = db.LedProject.Find(projectId);
unmittelbar nach dem Aufrufdb.SaveChanges();
? Ist es immer noch null ist? - Wenn ich Anrufe
var project2 = db.LedProject.Find(projectId);
direkt nachdb.SaveChanges();
der neue Wert ist nicht zugewiesen. Also ich gedebuggt die Zeilen im detail. Ich habe herausgefunden, wenn ich einen Haltepunkt nachproject.ResponsibleUser = responsibleUser == null ? null : db.User.Find(responsibleUser.UserId);
den neuen Wert nicht zugewiesen ist. Wenn ich einen breakpoint vor die Zeile und Schritt über das assigment (F10), der Wert ist gesetzt. Dieses Verhalten ist wiederholbar! Sehr seltsames Verhalten - Endlich habe ich es gelöst! Es scheint ein problem waren mit lazy loading der Navigationselemente. Wenn ich das erste laden zu
LedProject project = db.LedProject.Include("ResponsibleUser").Where(p => p.ProjectId == projectId).FirstOrDefault();
es funktioniert wie vorgesehen! - So in diesem Fall
project.ResponsibleUser
null war aufgrund der fehlenden enthalten. Zu raten, würde ich sagen, dass die Einstellung dieser Eigenschaft auf null, wenn es (irgendwie) schon meinte, war, dass EF angenommen, nichts hatte sich verändert, daher verändern Sie war nicht beibehalten. - Es scheint, dass die Eigenschaft geladen wurde, wenn ich versuchte, Sie zu ordnen
null
. Da wurde die Eigenschaft nicht überschrieben, wenn die assigment war einmal aufgerufen. Als ich es ein zweites mal direkt nach der (in der Uhr - Fenster) die Zuweisung richtig gemacht wurde - Schön finden! Sie soll die Frage beantwortet sich selbst, und dann zu akzeptieren. So sonst noch jemanden, der ein ähnliches problem kann möglicherweise finden Sie die Antwort.
- Das war mein plan, aber es ist ein 8h selbst beantworten zu sperren, so werde ich es jetzt tun
Du musst angemeldet sein, um einen Kommentar abzugeben.
Liegt das problem in der lazy loading von der navigationseigenschaft. Es scheint, dass der Wert zunächst auf null gesetzt und danach aus der Datenbank geladen. Also den gewünschten Wert (null in meinem Fall) ist außer Kraft gesetzt, indem Sie den momentan gespeicherten Wert in der Datenbank.
Diese lädt die ResponsibleUser, wenn die Projekt geladen wird. Damit endlich mein Problem gelöst!
Find()
und verwendenWhere()
statt. War punching mein Gesicht, bis ich das gefunden, vielen Dank.official
Weg? ist es irgendwo dokumentiert? es fühlt sich an wie ein bug.Wie boindiil sagte, das problem mit der lazy loading. Jedoch, Sie nur laden Sie die Unterkunft, wenn Sie wollen zu null, so dass die Entity Framework-Maschinen werden wissen, es hat sich geändert. Der code könnte so Aussehen:
Denke ich, es sollte eine Möglichkeit zur Nutzung von db.ChangeTracker zu zwingen, zu sparen, ohne die Last, aber ich diese noch nicht gefunden haben (und die wenigen Dinge, die ich versucht habe schien wirklich hacky).
ResponsibleUser
wird es in den Arbeitsspeicher zu laden und speichern Sie die änderungen auf null.Herausgefunden, der beste Weg, dies zu tun, ohne zu eifrig laden Sie den navigation-Eigenschaft, so können Sie immer noch verwenden, EF-s
Find()
und nicht um einen hack.Verwenden eine primitive ID neben der navigation Eigenschaft, wo der Typ ist, was die Navigations-Eigenschaften-ID-Typ (in der Regel Zeichenfolge für Benutzer), e.g:
Aktualisieren Sie die Zeichenfolge mit der navigation-Eigenschaft, wo Sie den Eintrag anlegen und dann, wenn Sie möchten, entfernen Sie die Beziehung nur tun
ledProject.ResponsibleUserId = null
.Wenn Sie den Namen der id etwas anderes als Navigations-Eigenschaften: name + id am Ende dann benötigen Sie Anmerkungen oder fluent-api zum anzeigen, denke ich.
Weitere Infos hier: In welchen Szenarien muss ich die foreign keys UND die Navigations-Eigenschaften, die in entity framework
Ich lief in dieses problem, und kommen mit einem kleinen "hack" nicht funktioniert lazy loading.
Einfach definieren Sie die Eigenschaft auf Ihrer Modell -
Jetzt müssen Sie nicht haben, um eifrig laden Sie den navigation-Eigenschaft, und wenn er auf null arbeiten. Noch wichtiger ist, indem man den hack direkt in Ihre Person, Sie müssen nicht daran denken, zu tun, explizite Kontrollen überall sonst in der codebase.
Beginnend mit dem Entity Framework 5.0:
https://msdn.microsoft.com/en-us/data/jj713564.aspx
Können Sie alle Navigations-Eigenschaften auf null so aus : ( Sie müssen Ihre EF-Kontext),hier : importierte IEnumerable < YourEntity>
mit GetReferenceProperties definiert als :
Sehen https://docs.microsoft.com/en-us/ef/ef6/fundamentals/relationships.
Den Erstellen und ändern von Beziehungen Abschnitt wird erläutert, was passiert, in Bezug auf die foreign key-Eigenschaft und die Navigations-Eigenschaft sowohl bei der Zuweisung und Einstellung auf null.
Gibt es einige änderungen in EF5 und nach vorne, aber der Schlüssel ist die Definition der foreign key-Eigenschaft, so dass die Beziehung ist nicht mehr ein unabhängige Vereinigung (es fehlt die foreign key-Eigenschaft).
Als weiteren workaround, den ich kompiliert habe zwei Methoden in eine extension-Methode:
Dies ermöglicht die Versorgung einer DbContext, wenn Sie eine haben, in welchem Falle dies verwendet wird, die effizienteste Methode, und legen Sie die CurrentValue der Eintrag-Verweis auf null.
Wenn keine DBContext wird geliefert, es wird lazy load erste.
Hinweis, dieses Problem ist im wesentlichen ein Duplikat von: Entity Framework werden nur verknüpfte Entität-Eigenschaft auf "null", wenn ich erstmal das Grundstück und Festlegen eines Fremdschlüssels auf null bei der Verwendung von entity framework code first