ASP.NET MVC 4, EF5, Unique property in model - best practice?

前端 未结 7 546
隐瞒了意图╮
隐瞒了意图╮ 2020-12-13 07:24

ASP.NET MVC 4, EF5, Code First, SQL Server 2012 Express

What is best practice to enforce a unique value in a model? I have a places class that has a

7条回答
  •  不知归路
    2020-12-13 07:49

    Faced similar issue in my ASP.NET Razor Page Project. Creating custom UniqueDataAttribute didn't work, because on Edit, it would throw an error if you're not changing unique field.

    I needed unique Book Name. This is how I resolved:

    1. I added unique constraint to the field in database via EF Core migrations. Added following in ApplicationDbContext class and then ran migration.

    Code:

    protected override void OnModelCreating(ModelBuilder builder)
            {
                builder.Entity()
                    .HasIndex(u => u.Name)
                    .IsUnique();
            }
    
    1. Next, created helper/extension method as follows.

    Code:

            // Validate uniqueness of Name field in database.
            // If validation is done on existing record, pass the id of the record.
            // Else, if validating new record Name, then id is set to dummy key integer -1
            public static bool UniqueNameInDb(this string data, ApplicationDbContext db, int id = -1)
            {
                var duplicateData = from o in db.Book
                                    where o.Name == data && o.Id != id
                                    select o;
                if(duplicateData.Any())
                {
                    return false;
                }
                return true;
            }
        }
    
    1. Then used it in Create and Edit page model in OnPost() method as follows.

    Create model:

    public async Task OnPost()
            {
                if(ModelState.IsValid)
                {
                    if (!Book.Name.UniqueNameInDb(_db)) //<--Uniqueness validation
                    {
                        ModelState.AddModelError("Book.Name", "Name already exist"); //<-- Add error to the ModelState, that would be displayed in view.
                        return Page();
                    }
    
                    await _db.Book.AddAsync(Book);
                    await _db.SaveChangesAsync();
    
                    return RedirectToPage("Index");
    
                }
                else
                {
                    return Page();
                }
            }
    

    Edit Model:

    public async Task OnPost()
            {
                if(ModelState.IsValid)
                {
                    var bookFromDb = await _db.Book.FindAsync(Book.Id);
                    if (!Book.Name.UniqueNameInDb(_db, Book.Id)) //<--Uniqueness validation
                    {
                        ModelState.AddModelError("Book.Name", "Name already exist"); //<-- Add error to the ModelState, that would be displayed in view.
                        return Page();
                    }
                    bookFromDb.Name = Book.Name;
                    bookFromDb.Author = Book.Author;
    
                    await _db.SaveChangesAsync();
    
                    return RedirectToPage("Index");
                }
    
                return Page();
            }
    

    PS: Your Razor view should've Model validation set on in the form to capture and display the error.

    i.e,

    and below validation against the field.

    
    

提交回复
热议问题