如何在 Entity Framework Code First 中使属性唯一
Posted
技术标签:
【中文标题】如何在 Entity Framework Code First 中使属性唯一【英文标题】:How to make a property unique in Entity Framework Code First 【发布时间】:2019-05-19 23:49:00 【问题描述】:这是我的User
模型类:
public class User
public int Id get; set;
[Required]
[MaxLength(100)]
public string FullName get; set;
[Required]
[MaxLength(30)]
[Remote("IsUsernameExists", "Home", HttpMethod = "Post")]
public string UserName get; set;
[Required]
[RegularExpression(@"^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]2,5)$"]
public string Email get; set;
[Required]
[StringLength(maximumLength: 18, MinimumLength = 8)]
public string Password get; set;
这是Home
控制器中的IsUsernameExists
方法
public JsonResult IsUsernameExists(string UserName)
return Json(!db.Users.Any(x => x.Username == UserName), JsonRequestBehavior.AllowGet);
但它不起作用。任何进一步的帮助将不胜感激!
【问题讨论】:
不完全是什么意思?您收到任何异常或错误消息?出乎意料的结果?您需要更具体地了解您的问题。 什么也没发生。当我输入一个已经存在的用户名时,它将进入数据库并记录它 尝试使用x => x.Username == UserName.ToLowerInvariant()
并告诉我它是否有效!
还是什么都没发生
您的UserName
也可能包含空格。也可以在ToLower
方法之后尝试Trim
方法,看看是否有效!
【参考方案1】:
您可以使用DataAnnotation
和FluentApi
来创建模型属性Unique
,如下所示:
使用数据注解:
[Required]
[StringLength(30)]
[Index("Ix_UserName",Order =1,IsUnique =true)]
public string UserName get; set;
使用 Fluent Api:
在实体框架 >= 6.2 中,
在DbContext
:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>().Property(u => u.UserName).HasMaxLength(30);
modelBuilder.Entity<User>().HasIndex(u => u.UserName).IsUnique();
在实体框架中
在DbContext
:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<User>().Property(t => t.UserName).HasMaxLength(30)
.HasColumnAnnotation(IndexAnnotation.AnnotationName, new IndexAnnotation(new IndexAttribute("Ix_UserName")IsUnique = true));
记住:使用Index
属性,您还必须使用StringLength
属性。
为了使RemoteAttibute
正常工作,请在UserName
属性上写下您的RemoteAttibute
,如下所示:
[Required]
[StringLength(30)]
[Index("Ix_UserName",Order =1,IsUnique =true)]
[Remote("IsUserNameExist", "Home", AdditionalFields = "Id", ErrorMessage = "User Name already exists")]
public string UserName get; set;
然后HomeController
中的IsUserNameExist
方法如下:
public JsonResult IsUserNameExist(string UserName, int? Id)
var IsUserNameExists = db.Users.Any(x => x.UserName== UserName && x.Id != Id);
return Json(!IsUserNameExists, JsonRequestBehavior.AllowGet);
最后确保您的视图包含以下jQuery
文件:
<script src="~/Scripts/jquery-version.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
现在一切正常!
【讨论】:
【参考方案2】:RemoteAttribute 与实体框架没有任何关系。它只是忽略了这个属性。此外,正如文档所述,它是一个 jQuery
验证属性,它应该只适用于前端部分。
如果User
既是 MVC 模型又是数据库实体,您应该为属性创建唯一索引。一种方法是使用DbContext
中的OnModelCreating
方法:
protected override void OnModelCreating(ModelBuilder modelBuilder)
modelBuilder.Entity<User>().HasIndex(x => new x.Username ).IsUnique();
然后创建一个迁移,将它应用到数据库中,你就可以开始了。但是,请注意保存副本时会出现异常,并确保正确处理。
【讨论】:
【参考方案3】:我在 HomeController 中创建了一个方法
public bool IsUserExist(string email)
return db.Users.Where(c => c.Email == email).IsAny();
在行动中
if( IsUserExist(model.Email) )
// my code
【讨论】:
以上是关于如何在 Entity Framework Code First 中使属性唯一的主要内容,如果未能解决你的问题,请参考以下文章