Ich habe die [Required]
Datenanmerkung einem meiner Modelle in einer ASP.NET MVC-Anwendung hinzugefügt . Nach dem Erstellen einer Migration führt das Ausführen des Update-Database
Befehls zu folgendem Fehler:
Der Wert NULL kann nicht in die Spalte 'Director', Tabelle 'MOVIES_cf7bad808fa94f89afa2e5dae1161e78.dbo.Movies' eingefügt werden. Spalte erlaubt keine Nullen. UPDATE schlägt fehl. Die Anweisung wurde beendet.
Dies liegt daran, dass einige Datensätze NULL in ihren Director
Spalten haben. Wie kann ich diese Werte automatisch in einen Standarddirektor (z. B. "John Doe") ändern?
Hier ist mein Modell:
public class Movie
{
public int ID { get; set; }
[Required]
public string Title { get; set; }
[DataType(DataType.Date)]
public DateTime ReleaseDate { get; set; }
[Required]
public string Genre { get; set; }
[Range(1,100)]
[DataType(DataType.Currency)]
public decimal Price { get; set; }
[StringLength(5)]
public string Rating { get; set; }
[Required] /// <--- NEW
public string Director { get; set; }
}
und hier ist meine letzte Migration:
public partial class AddDataAnnotationsMig : DbMigration
{
public override void Up()
{
AlterColumn("dbo.Movies", "Title", c => c.String(nullable: false));
AlterColumn("dbo.Movies", "Genre", c => c.String(nullable: false));
AlterColumn("dbo.Movies", "Rating", c => c.String(maxLength: 5));
AlterColumn("dbo.Movies", "Director", c => c.String(nullable: false));
}
public override void Down()
{
AlterColumn("dbo.Movies", "Director", c => c.String());
AlterColumn("dbo.Movies", "Rating", c => c.String());
AlterColumn("dbo.Movies", "Genre", c => c.String());
AlterColumn("dbo.Movies", "Title", c => c.String());
}
}
quelle
IS NULL
Prüfung durch Ihre Abfrage aktualisieren ."'John Doe'"
- Sie müssen SQL-Anführungszeichen verwenden.AlterColumn
aktuelle Werte aktualisiert werden? Es ist ein DDL-Befehl (kein DML-Befehl).Zusätzlich zur Antwort von @webdeveloper und @Pushpendra müssen Sie Ihrer Migration manuell Aktualisierungen hinzufügen, um vorhandene Zeilen zu aktualisieren. Beispielsweise:
Dies liegt daran, dass
AlterColumn
DDL erzeugt wird, um den Standardwert der Spalte auf einen bestimmten Wert in der Tabellenspezifikation festzulegen. Die DDL wirkt sich nicht auf vorhandene Zeilen in der Datenbank aus.Sie nehmen tatsächlich zwei Änderungen gleichzeitig vor (Festlegen der Standardeinstellung und Festlegen der Spalte NOT NULL), und jede davon ist einzeln gültig. Da Sie jedoch beide Änderungen gleichzeitig vornehmen, können Sie davon ausgehen, dass das System ' Verwirklichen Sie Ihre Absicht auf intelligente Weise und setzen Sie alle
NULL
Werte auf den Standardwert. Dies wird jedoch nicht immer erwartet.Angenommen, Sie legen nur den Standardwert für die Spalte fest und machen ihn nicht auf NULL. Sie erwarten offensichtlich nicht, dass alle NULL-Datensätze mit dem von Ihnen angegebenen Standard aktualisiert werden.
Meiner Meinung nach ist dies also kein Fehler, und ich möchte nicht, dass EF meine Daten so aktualisiert, wie ich es nicht ausdrücklich vorschreibe. Der Entwickler ist dafür verantwortlich, das System anzuweisen, was mit den Daten zu tun ist.
quelle
quelle
Ich bin mir nicht sicher, ob diese Option immer verfügbar war, stieß aber auf ein ähnliches Problem. Ich stellte fest, dass ich den Standardwert festlegen konnte, ohne manuelle Updates mithilfe der folgenden Schritte auszuführen
defaultValueSql: "'NY'"
Ich habe eine Fehlermeldung erhalten, als der angegebene Wert angegeben wurde.
"NY"
Dann wurde mir klar, dass sie einen SQL-Wert erwarten,"GETDATE()"
also habe ich es versucht"'NY'"
und das hat den Trick getanDie gesamte Linie sieht so aus
AddColumn("TABLE_NAME", "State", c => c.String(maxLength: 2, nullable: false, defaultValueSql: "'NY'"));
Dank dieser Antwort bin ich auf dem richtigen Weg
quelle
Seit EF Core 2.1 können Sie
MigrationBuilder.UpdateData
Werte ändern, bevor Sie die Spalte ändern (sauberer als bei Verwendung von Raw SQL):quelle
Ich habe festgestellt, dass es ausreicht, nur den Auto-Property Initializer für die Entitätseigenschaft zu verwenden, um die Aufgabe zu erledigen.
Beispielsweise:
quelle
Viele der anderen Antworten konzentrieren sich darauf, wie man manuell eingreift, wenn diese Probleme auftreten.
Beachten Sie, dass manuelle Änderungen, die an einem Migrationsskript vorgenommen werden, überschrieben werden, wenn Sie die Migration erneut durchführen. Bei der ersten Lösung ist es ziemlich einfach, EF so zu erweitern, dass im Rahmen der Migrationsgenerierung automatisch ein Standardwert für ein Feld definiert wird.
Die folgende Lösung kombiniert Attributnotation, Modellkonfigurationskonventionen und Spaltenanmerkungen, um Metadaten an einen benutzerdefinierten Migrationscodegenerator zu übergeben. Die Schritte 1 und 2 können für jedes betroffene Feld durch eine fließende Notation ersetzt werden, wenn Sie keine Attributnotation verwenden.
Hier sind viele Techniken im Spiel, zögern Sie nicht, einige oder alle zu verwenden. Ich hoffe, dass hier für alle ein Wert ist
Deklarieren Sie den Standardwert.
Erstellen Sie ein vorhandenes Attribut oder verwenden Sie es erneut, um den zu verwendenden Standardwert zu definieren. In diesem Beispiel erstellen wir ein neues Attribut namens DefaultValue, das von ComponentModel.DefaultValueAttribute erbt, da die Verwendung intuitiv ist und die Möglichkeit besteht, dass es vorhanden ist Codebasen implementieren dieses Attribut bereits. Bei dieser Implementierung müssen Sie nur dieses spezielle Attribut verwenden, um auf DefaultValueSql zuzugreifen, das für Datumsangaben und andere benutzerdefinierte Szenarien nützlich ist.
Implementierung
Attributdefinition
Erstellen Sie eine Konvention, um den Standardwert in die Spaltenanmerkungen einzufügen.
Spaltenanmerkungen werden verwendet, um benutzerdefinierte Metadaten zu Spalten an den Migrationsskriptgenerator weiterzuleiten.
Die Verwendung einer Konvention zeigt die Leistungsfähigkeit der Attributnotation, um zu vereinfachen, wie fließende Metadaten für viele Eigenschaften definiert und bearbeitet werden können, anstatt sie für jedes Feld einzeln anzugeben.
Hinzufügen der Konvention zum DbContext
Es gibt viele Möglichkeiten, dies zu erreichen. Ich möchte die Konventionen als ersten benutzerdefinierten Schritt in meiner ModelCreation-Logik deklarieren. Dies wird in Ihrer DbContext-Klasse sein.
Überschreiben des MigrationCodeGenerators
Nachdem diese Anmerkungen auf die Spaltendefinitionen im Modell angewendet wurden, müssen Sie den Migrationsskriptgenerator ändern, um diese Anmerkungen zu verwenden. Dafür werden wir von der erben,
System.Data.Entity.Migrations.Design.CSharpMigrationCodeGenerator
da wir nur eine minimale Menge an Änderungen injizieren müssen.Nachdem wir unsere benutzerdefinierte Anmerkung verarbeitet haben, müssen wir sie aus der Spaltendefinition entfernen, um zu verhindern, dass sie für die endgültige Ausgabe serialisiert wird.
Registrieren des CustomCodeGenerator Im
letzten Schritt müssen wir in der DbMigration-Konfigurationsdatei den zu verwendenden Codegenerator angeben und standardmäßig in Ihrem Migrationsordner nach Configuration.cs suchen ...
quelle
Aus irgendeinem Grund, dass ich mich nicht erklären konnte, funktioniert die genehmigte Antwort für mich nicht mehr.
Es hat auf einer anderen App funktioniert, auf der, an der ich arbeite, funktioniert es nicht.
Eine alternative, aber recht ineffiziente Lösung wäre es, die SaveChanges () -Methode wie unten gezeigt zu überschreiben. Diese Methode sollte sich in der Context-Klasse befinden.
quelle