Как обеспечить уникальное значение столбца внутри кода?

Я изучаю ASP.NET MVC и не понимаю, как обеспечить уникальные значения для столбцов (имя пользователя и адрес электронной почты) для таблицы.

Может ли кто-нибудь помочь мне с образцом кода или ссылкой на учебник, который показывает и объясняет это?

ИЗМЕНИТЬ:

Я знаю, что могу применить уникальное ключевое ограничение к столбцам таблицы и добиться этого. Однако я хочу знать, как я могу добиться этого с помощью кода ASP.NET MVC?

ОБНОВЛЕНИЕ:

Я хочу выполнить проверку в своем приложении, чтобы в DAL не передавались повторяющиеся значения, т.е. выполнить проверку перед вставкой новой строки.


person mliya    schedule 05.09.2011    source источник
comment
Вопрос, который вы задаете, связан с базой данных, а не с ASP.NET MVC.   -  person brodie    schedule 05.09.2011
comment
@brodie: Однако вы правы, я хотел узнать это с точки зрения ASP.NET MVC, поэтому обновил вопрос.   -  person mliya    schedule 05.09.2011
comment
@mliya, ты уже нашел решение этой проблемы?   -  person Asbjørn Ulsberg    schedule 13.08.2012


Ответы (2)


Млия, это то, что вы контролируете на уровне базы данных, а не на уровне приложения.

Если вы проектируете базу данных с таблицей users, в которой вы хотите ограничить столбцы username и email значением UNIQUE, вам следует создать УНИКАЛЬНЫЙ ИНДЕКС для таких столбцов.

не зная вашей серверной базы данных (mySQL, SQL Server, MS Access, Oracle...), это не тот случай, чтобы показать вам изображения или рассказать многое другое, просто создайте таблицу с помощью дизайнера и добавьте эти уникальные ограничения к этим столбцам и по дизайну вы будете уверены, что для имени пользователя и электронной почты никогда не будут вставлены повторяющиеся значения.

Я также предлагаю вам создать столбец ID, который будет установлен как PK (первичный ключ, что означает, что он будет автоматически установлен как NON NULL и UNIQUE).

Конечно, из вашего приложения ASP.NET MVC вы должны убедиться, что никакие повторяющиеся значения не передаются в DAL для имени пользователя и электронной почты. Вы можете сделать это по-разному, проще всего, вероятно, проверить перед вставкой новой строки, существует ли уже какой-либо пользователь с таким именем пользователя и/или адресом электронной почты, и если да, вы можете отобразить сообщение с уведомлением, в котором пользователю предлагается выбрать другую пару значений. .

person Davide Piras    schedule 05.09.2011
comment
Да, это то, что я хочу сделать, проверить в своем приложении, что в DAL не передаются повторяющиеся значения, т.е. добиться проверки перед вставкой новой строки. Можете ли вы помочь мне в этом отношении? Заранее спасибо! - person mliya; 05.09.2011
comment
покажите нам, как вы делаете вставку прямо сейчас, и давайте посмотрим, как мы можем добавить проверку ;-) - person Davide Piras; 05.09.2011
comment
Можете ли вы предложить какой-нибудь общий пример кода, демонстрирующий такую ​​функциональность? - person mliya; 05.09.2011
comment
Если вы проверите перед вставкой, у вас все еще есть шанс, что 2 идентичных имени пользователя попадут в базу данных. Я признаю, что окно небольшое, но может произойти и будет более вероятным, если приложение будет занято и распределено по нескольким серверам. Поэтому я думаю, что ошибка базы данных также должна быть обработана. - person Dale K; 11.08.2012

В архитектуре ASP.NET MVC большую часть проверки следует выполнять в модели, но с такими низкоуровневыми правилами проверки иногда это невозможно. Тогда вам следует искать ответы на предметно-ориентированном дизайне (DDD), где Службы приложений могут решить такие низкоуровневые задачи.

Службы приложений будут иметь доступ к базе данных (либо напрямую, либо, что еще лучше, косвенно через репозитории) и может выполнять низкоуровневую проверку и выдавать ValidationException или что-то подобное (с подробной информацией, с которой Controller может действовать и отвечать пользователю), когда предварительное условие или бизнес-правило не выполняются.

Архитектура S#arp реализует все это в рамках передовой практики, которую вы можете использовать в качестве основы для своего ASP. Приложения .NET MVC. Он очень самоуверен в отношении принципов DDD и NHibernate, и иногда он будет навязывать вам то, как вы делаете что-то, что в некотором роде важно. Самое главное в этом то, что он учит вас, как справляться с такого рода проблемами.

Чтобы ответить на ваш вопрос более конкретно и в духе DDD, я бы решил его так:

public class UserController
{
    private readonly IUserService userService;

    public UserController(IUserService userService)
    {
        // The IUserService will be injected into the controller with
        // an "Inversion of Control" container like NInject, Castle Windsor
        // or StructureMap:
        this.userService = userService;
    }

    public ActionResult Save(UserFormModel userFormModel)
    {
        if (userFormModel.IsValid)
        {
            try
            {
                // Mapping can be performed by AutoMapper or some similar library
                UserDto userDto = Mapper.Map<UserDto>(userFormModel);
                this.userService.Save(userDto);
            }
            catch (ValidationException ve)
            {
                ViewBag.Error = ve.Detail;
            }
        }

        // Show validation errors or redirect to a "user saved" page.
    }
}

public class UserService : IUserService
{
    private readonly IUserRepository userRepository;

    public UserService(IUserRepository userRepository)
    {
        // The IUserRepository will be injected into the service with
        // an "Inversion of Control" container like NInject, Castle Windsor
        // or StructureMap:
        this.userRepository = userReposityr;
    }

    public UserDto Save(UserDto userDto)
    {
        using (this.userRepository.BeginTransaction())
        {
            if (!this.userRepository.IsUnique(userDto.UserName))
            {
                // The UserNameNotUniqueValidationException will inherit from ValidationException
                // and build a Detail object that contains information that can be presented to
                // a user.
                throw new UserNameNotUniqueValidationException(userDto.UserName);
            }

            userDto = this.userRepository.Save(userDto);
            this.userRepository.CommitTransaction();

            return userDto;
        }
    }
}
person Asbjørn Ulsberg    schedule 05.09.2011
comment
Спасибо за ваш ответ. Однако, поскольку я изучаю asp.net mvc, я не слишком уверен в том, действительно ли этот ответ является базовым или включает в себя (некоторые) расширенные функции. Не могли бы вы прокомментировать это - person mliya; 05.09.2011
comment
Мой ответ — это попытка научить лучшей практике реализации n-уровневого приложения ASP.NET MVC. Это в основном актуально, если вы хотите создавать очень крупномасштабные приложения, но как только у вас есть все необходимое для IoC и т. д., это не намного сложнее, чем более простая реализация. Если вы хотите, чтобы ваше приложение росло, это способ сделать это. - person Asbjørn Ulsberg; 05.09.2011
comment
Если я не ошибаюсь, это решение выполняет проверку базы данных перед сохранением, и теоретически 2 пользователя все равно могут вводить данные одновременно, оба проходят тест IsUnique, но тогда один не пройдет тест уникальное ограничение базы данных. Я предполагаю, что try/catch вокруг сохранения, который переводит ошибку БД в ошибку пользователя, справится с этим? - person Dale K; 11.08.2012
comment
@DaleBurrell, вы правы, но я думаю, что атомарность лучше достигается за счет использования транзакций, поэтому я добавил область транзакций вокруг уникальных операций / операций сохранения, которые будут обрабатывать условия гонки, подобные той, которую вы описываете. - person Asbjørn Ulsberg; 13.08.2012