J'ai ajouté l' [Required]
annotation de données à l'un de mes modèles dans une application ASP.NET MVC . Après avoir créé une migration, l'exécution de la Update-Database
commande entraîne l'erreur suivante:
Impossible d'insérer la valeur NULL dans la colonne 'Director', table 'MOVIES_cf7bad808fa94f89afa2e5dae1161e78.dbo.Movies'; La colonne n'autorise pas les valeurs nulles. UPDATE échoue. La déclaration a été terminée.
Cela est dû au fait que certains enregistrements ont NULL dans leurs Director
colonnes. Comment puis-je changer automatiquement ces valeurs en un directeur par défaut (disons "John Doe")?
Voici mon modèle:
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; }
}
et voici ma dernière 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());
}
}
la source
IS NULL
check par votre requête."'John Doe'"
- vous devez utiliser des guillemets SQL.AlterColumn
mettre à jour les valeurs actuelles? Il s'agit d'une commande DDL (pas DML).En plus de la réponse de @webdeveloper et @Pushpendra, vous devez ajouter manuellement des mises à jour à votre migration pour mettre à jour les lignes existantes. Par exemple:
C'est parce que
AlterColumn
produit DDL pour définir la valeur par défaut de la colonne sur une valeur spécifique dans la spécification de table. Le DDL n'affecte pas les lignes existantes dans la base de données.Vous effectuez en fait deux modifications en même temps (définissant la valeur par défaut et rendant la colonne NOT NULL) et chacune d'elles est valide individuellement, mais puisque vous effectuez les deux en même temps, vous pouvez vous attendre à ce que le système ' 'réalisez intelligemment votre intention et définissez toutes les
NULL
valeurs sur la valeur par défaut, mais ce n'est pas ce qui est attendu tout le temps.Supposons que vous ne définissiez que la valeur par défaut de la colonne et que vous ne la définissiez pas NULL. Vous ne vous attendez évidemment pas à ce que tous les enregistrements NULL soient mis à jour avec la valeur par défaut que vous fournissez.
Donc, à mon avis, ce n'est pas un bogue, et je ne veux pas qu'EF mette à jour mes données de la manière que je ne lui dis pas explicitement de le faire. Le développeur est responsable d'indiquer au système ce qu'il faut faire avec les données.
la source
la source
Je ne sais pas si cette option était toujours là, mais juste rencontré un problème similaire, j'ai constaté que j'étais en mesure de définir la valeur par défaut sans exécuter de mises à jour manuelles en utilisant ce qui suit
defaultValueSql: "'NY'"
J'ai eu une erreur lorsque la valeur fournie était
"NY"
alors j'ai réalisé qu'ils attendaient une valeur SQL comme"GETDATE()"
si j'ai essayé"'NY'"
et cela a fait l'affairetoute la ligne ressemble à ceci
AddColumn("TABLE_NAME", "State", c => c.String(maxLength: 2, nullable: false, defaultValueSql: "'NY'"));
Grâce à cette réponse , m'a mis sur la bonne voie
la source
Depuis EF Core 2.1, vous pouvez utiliser
MigrationBuilder.UpdateData
pour modifier les valeurs avant de modifier la colonne (plus propre que d'utiliser du SQL brut):la source
J'ai trouvé que le simple fait d'utiliser l'initialiseur de propriété automatique sur la propriété de l'entité était suffisant pour faire le travail.
Par exemple:
la source
La plupart des autres réponses se concentrent sur la manière d'intervenir manuellement lorsque ces problèmes surviennent.
Gardez à l'esprit que les modifications manuelles appliquées à un script de migration seront écrasées si vous rééchafaudez la migration. Pour la première solution, il est assez facile d'étendre EF pour définir automatiquement une valeur par défaut sur un champ dans le cadre de la génération de migration.
La solution suivante combine la notation d'attribut, les conventions de configuration du modèle et les annotations de colonne pour transmettre les métadonnées à un générateur de code de migration personnalisé. Les étapes 1 et 2 peuvent être remplacées par une notation fluide pour chaque champ affecté si vous n'utilisez pas la notation attributaire.
Il y a beaucoup de techniques en jeu ici, n'hésitez pas à en utiliser certaines ou toutes, j'espère qu'il y a de la valeur pour tout le monde ici
Déclarez la valeur par défaut
Créez ou réutilisez un attribut existant pour définir la valeur par défaut à utiliser, pour cet exemple, nous allons créer un nouvel attribut appelé DefaultValue qui hérite de ComponentModel.DefaultValueAttribute, car l'utilisation est intuitive et il y a une chance que existant les bases de code implémentent déjà cet attribut. Avec cette implémentation, vous devez uniquement utiliser cet attribut spécifique pour accéder à DefaultValueSql, ce qui est utile pour les dates et autres scénarios personnalisés.
la mise en oeuvre
Attirer la définition
Créez une convention pour injecter la valeur par défaut dans les annotations de colonne Les annotations de
colonne sont utilisées pour transmettre des métadonnées personnalisées sur les colonnes au générateur de script de migration.
L'utilisation d'une convention pour ce faire démontre la puissance de la notation d'attribut pour simplifier la façon dont les métadonnées fluides peuvent être définies et manipulées pour de nombreuses propriétés plutôt que de les spécifier individuellement pour chaque champ.
Ajouter la Convention au DbContext
Il existe de nombreuses façons d'y parvenir , j'aime déclarer les conventions comme la première étape personnalisée dans ma logique ModelCreation, ce sera dans votre classe DbContext.
Remplacer le MigrationCodeGenerator
Maintenant que ces annotations ont été appliquées aux définitions de colonne dans le modèle, nous devons modifier le générateur de script de migration pour utiliser ces annotations. Pour cela, nous hériterons de la
System.Data.Entity.Migrations.Design.CSharpMigrationCodeGenerator
car il nous suffit d'injecter un minimum de changement.Une fois que nous avons traité notre annotation personnalisée, nous devons la supprimer de la définition de colonne pour éviter qu'elle ne soit sérialisée dans la sortie finale.
Enregistrer le CustomCodeGenerator
Dernière étape, dans le fichier de configuration DbMigration, nous devons spécifier le générateur de code à utiliser, recherchez Configuration.cs dans votre dossier de migration par défaut ...
la source
Pour une raison quelconque, que je n'étais pas en mesure de m'expliquer, la réponse approuvée ne fonctionne plus pour moi.
Cela a fonctionné sur une autre application, sur celle sur laquelle je travaille, ce n'est pas le cas.
Donc, une solution alternative, mais assez inefficace , serait de remplacer la méthode SaveChanges () comme indiqué ci-dessous. Cette méthode doit être sur la classe Context.
la source