Y a-t-il un moyen "élégant" de donner une valeur par défaut à une propriété spécifique ?
Peut-être par DataAnnotations, quelque chose comme :
[DefaultValue("true")]
public bool Active { get; set; }
Merci.
Y a-t-il un moyen "élégant" de donner une valeur par défaut à une propriété spécifique ?
Peut-être par DataAnnotations, quelque chose comme :
[DefaultValue("true")]
public bool Active { get; set; }
Merci.
Cela fait un moment, mais je laisse une note pour les autres. J'ai accompli ce qui est nécessaire avec un attribut et j'ai décoré les champs de ma classe de modèle avec cet attribut comme je le souhaite.
[SqlDefaultValue(DefaultValue = "getutcdate()")]
public DateTime CreatedDateUtc { get; set; }
J'ai eu l'aide de ces 2 articles :
Ce que j'ai fait :
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class SqlDefaultValueAttribute : Attribute
{
public string DefaultValue { get; set; }
}
modelBuilder.Conventions.Add( new AttributeToColumnAnnotationConvention<SqlDefaultValueAttribute, string>("SqlDefaultValue", (p, attributes) => attributes.Single().DefaultValue));
private void SetAnnotatedColumn(ColumnModel col)
{
AnnotationValues values;
if (col.Annotations.TryGetValue("SqlDefaultValue", out values))
{
col.DefaultValueSql = (string)values.NewValue;
}
}
Ensuite, dans le constructeur de la configuration des migrations, enregistrer le générateur SQL personnalisé.
SetSqlGenerator("System.Data.SqlClient", new CustomMigrationSqlGenerator());
Les réponses ci-dessus ont vraiment aidé, mais n'ont fourni qu'une partie de la solution. Le problème majeur est que dès que vous supprimez l'attribut de valeur par défaut, la contrainte sur la colonne dans la base de données ne sera pas supprimée. Ainsi, la valeur par défaut précédente restera dans la base de données.
Voici une solution complète au problème, comprenant la suppression des contraintes SQL lors de la suppression de l'attribut. J'utilise également l'attribut DefaultValue
natif du framework .NET.
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
[DefaultValue("getutcdate()")]
public DateTime CreatedOn { get; set; }
Pour que cela fonctionne, vous devez mettre à jour les fichiers IdentityModels.cs et Configuration.cs
Ajoutez/mettez à jour cette méthode dans votre classe ApplicationDbContext
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
var convention = new AttributeToColumnAnnotationConvention("SqlDefaultValue", (p, attributes) => attributes.SingleOrDefault().Value.ToString());
modelBuilder.Conventions.Add(convention);
}
Mettez à jour le constructeur de votre classe Configuration
en enregistrant un générateur SQL personnalisé, comme ceci:
internal sealed class Configuration : DbMigrationsConfiguration
{
public Configuration()
{
// Générateur SQL de valeur par défaut
SetSqlGenerator("System.Data.SqlClient", new DefaultValueSqlServerMigrationSqlGenerator());
}
}
Ensuite, ajoutez une classe de générateur SQL personnalisé (vous pouvez l'ajouter au fichier Configuration.cs ou à un fichier séparé)
internal class DefaultValueSqlServerMigrationSqlGenerator : SqlServerMigrationSqlGenerator
{
private int dropConstraintCount;
protected override void Generate(AddColumnOperation addColumnOperation)
{
SetAnnotatedColumn(addColumnOperation.Column, addColumnOperation.Table);
base.Generate(addColumnOperation);
}
protected override void Generate(AlterColumnOperation alterColumnOperation)
{
SetAnnotatedColumn(alterColumnOperation.Column, alterColumnOperation.Table);
base.Generate(alterColumnOperation);
}
protected override void Generate(CreateTableOperation createTableOperation)
{
SetAnnotatedColumns(createTableOperation.Columns, createTableOperation.Name);
base.Generate(createTableOperation);
}
protected override void Generate(AlterTableOperation alterTableOperation)
{
SetAnnotatedColumns(alterTableOperation.Columns, alterTableOperation.Name);
base.Generate(alterTableOperation);
}
private void SetAnnotatedColumn(ColumnModel column, string tableName)
{
if (column.Annotations.TryGetValue("SqlDefaultValue", out var values))
{
if (values.NewValue == null)
{
column.DefaultValueSql = null;
using var writer = Writer();
// Suppression de la contrainte
writer.WriteLine(GetSqlDropConstraintQuery(tableName, column.Name));
Statement(writer);
}
else
{
column.DefaultValueSql = (string)values.NewValue;
}
}
}
private void SetAnnotatedColumns(IEnumerable columns, string tableName)
{
foreach (var column in columns)
{
SetAnnotatedColumn(column, tableName);
}
}
private string GetSqlDropConstraintQuery(string tableName, string columnName)
{
var tableNameSplitByDot = tableName.Split('.');
var tableSchema = tableNameSplitByDot[0];
var tablePureName = tableNameSplitByDot[1];
var str = $@"DECLARE @var{dropConstraintCount} nvarchar(128)
SELECT @var{dropConstraintCount} = name
FROM sys.default_constraints
WHERE parent_object_id = object_id(N'{tableSchema}.[{tablePureName}]')
AND col_name(parent_object_id, parent_column_id) = '{columnName}';
IF @var{dropConstraintCount} IS NOT NULL
EXECUTE('ALTER TABLE {tableSchema}.[{tablePureName}] DROP CONSTRAINT [' + @var{dropConstraintCount} + ']')";
dropConstraintCount++;
return str;
}
}
Les propriétés de votre modèle ne doivent pas nécessairement être des "propriétés automatiques", même si c'est plus facile. Et l'attribut DefaultValue est vraiment seulement une métadonnée informative. La réponse acceptée ici est une alternative à l'approche du constructeur.
public class Track
{
private const int DEFAULT_LENGTH = 400;
private int _length = DEFAULT_LENGTH;
[DefaultValue(DEFAULT_LENGTH)]
public int LongueurEnMètres {
get { return _length; }
set { _length = value; }
}
}
vs.
public class Track
{
public Track()
{
LongueurEnMètres = 400;
}
public int LongueurEnMètres { get; set; }
}
Cela ne fonctionnera que pour les applications créant et consommant des données en utilisant cette classe spécifique. Habituellement, ce n'est pas un problème si le code d'accès aux données est centralisé. Pour mettre à jour la valeur dans toutes les applications, vous devez configurer la source de données pour définir une valeur par défaut. La réponse de Devi ici montre comment cela peut être fait en utilisant des migrations, SQL, ou n'importe quel langage que votre source de données utilise.
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.