J'utilise Entity Framework 4.3 et j'utilise Code Fist.
J'ai un cours
public class User
{
public int UserId{get;set;}
public string UserName{get;set;}
}
Comment puis-je dire à Entity Framework que UserName doit être unique lors de la création d'une table de base de données? Je préférerais utiliser des annotations de données plutôt qu'un fichier de configuration si possible.
Dans Entity Framework 6.1+, vous pouvez utiliser cet attribut sur votre modèle:
[Index(IsUnique=true)]
Vous pouvez le trouver dans cet espace de noms:
using System.ComponentModel.DataAnnotations.Schema;
Si votre champ de modèle est une chaîne, assurez-vous qu'il n'est pas défini sur nvarchar (MAX) dans SQL Server ou vous verrez cette erreur avec Entity Framework Code First:
La colonne 'x' de la table 'dbo.y' est d'un type non valide pour une utilisation en tant que colonne clé dans un index.
La raison est pour cela:
SQL Server conserve la limite de 900 octets pour la taille totale maximale de toutes les colonnes de clé d'index. "
(de: http://msdn.Microsoft.com/en-us/library/ms191241.aspx )
Vous pouvez résoudre ce problème en définissant une longueur de chaîne maximale sur votre modèle:
[StringLength(450)]
Votre modèle ressemblera maintenant à ceci dans EF CF 6.1+:
public class User
{
public int UserId{get;set;}
[StringLength(450)]
[Index(IsUnique=true)]
public string UserName{get;set;}
}
Mise à jour:
si vous utilisez Fluent:
public class UserMap : EntityTypeConfiguration<User>
{
public UserMap()
{
// ....
Property(x => x.Name).IsRequired().HasMaxLength(450).HasColumnAnnotation("Index", new IndexAnnotation(new[] { new IndexAttribute("Index") { IsUnique = true } }));
}
}
et utilisez dans votre modelBuilder:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// ...
modelBuilder.Configurations.Add(new UserMap());
// ...
}
Mise à jour 2
pour EntityFrameworkCore, voir également ce sujet: https://github.com/aspnet/EntityFrameworkCore/issues/1698
Mise à jour 3
pour EF6.2, voir: https://github.com/aspnet/EntityFramework6/issues/274
Mise à jour 4
ASP.NET Core Mvc 2.2 avec EF Core:
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Unique { get; set; }
EF ne prend pas en charge les colonnes uniques sauf les clés. Si vous utilisez EF Migrations, vous pouvez forcer EF à créer un index unique sur la colonne UserName
(dans le code de migration, pas par une annotation), mais l'unicité ne sera appliquée que dans la base de données. Si vous essayez de sauvegarder une valeur en double, vous devrez intercepter une exception (violation de contrainte) déclenchée par la base de données.
À partir de votre code, il devient évident que vous utilisez POCO. Il est inutile d'avoir une autre clé: vous pouvez ajouter un index comme suggéré par juFo .
Si vous utilisez l'API Fluent au lieu d'attribuer la propriété UserName, votre annotation de colonne devrait ressembler à ceci:
this.Property(p => p.UserName)
.HasColumnAnnotation("Index", new IndexAnnotation(new[] {
new IndexAttribute("Index") { IsUnique = true }
}
));
Cela créera le script SQL suivant:
CREATE UNIQUE NONCLUSTERED INDEX [Index] ON [dbo].[Users]
(
[UserName] ASC
)
WITH (
PAD_INDEX = OFF,
STATISTICS_NORECOMPUTE = OFF,
SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF,
DROP_EXISTING = OFF,
ONLINE = OFF,
ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON
) ON [PRIMARY]
Si vous essayez d'insérer plusieurs utilisateurs ayant le même nom d'utilisateur, vous obtiendrez une exception DbUpdateException avec le message suivant:
Cannot insert duplicate key row in object 'dbo.Users' with unique index 'Index'.
The duplicate key value is (...).
The statement has been terminated.
Là encore, les annotations de colonne ne sont pas disponibles dans Entity Framework avant la version 6.1.
Notez que dans Entity Framework 6.1 (actuellement en version bêta) prendra en charge IndexAttribute pour annoter les propriétés de l'index, ce qui donnera automatiquement un index (unique) dans vos migrations Code First.