Entity Framework 4 - уникальная проблема имени пользователя и столбца электронной почты - PullRequest
2 голосов
/ 02 апреля 2011

У меня есть сущность User в моей модели сущности:

http://i.stack.imgur.com/QXMYI.jpg

Имя пользователя и адрес электронной почты должны быть уникальными, но пока EF4 не поддерживает это.

Итак, я написал этот код для обеспечения уникальности:

public void CreateNewUser(string i_UserName, string i_Email)
{
    using (ModelContainer context = new ModelContainer())
    {
        User usr;

        usr = context.UserSet.Where(u => u.Username == i_UserName).SingleOrDefault();
        if (usr != null)
            throw new Exception("Username not unique");

        usr = context.UserSet.Where(u => u.Email == i_Email).SingleOrDefault();
        if (usr != null)
            throw new Exception("Email not unique");

        context.UserSet.AddObject(new User() { Username = i_UserName, Email = i_Email });
        context.SaveChanges();                               
    }
}

Если это правильный подход, могу ли я автоматически преформировать этот код всякий раз, когда вызывается context.UserSet.AddObject()? Или существует более элегантный способ?

Ответы [ 4 ]

5 голосов
/ 02 апреля 2011

Я не знаю более элегантного способа. Вместо использования SingleOrDefault, я думаю, вы хотите что-то вроде:

bool isUniqueUserName = !context.UserSet.Any(u => u.Username == i_UserName); 

за производительность. Any() останавливается на первом совпадении и не должен перечислять всю последовательность.

2 голосов
/ 02 апреля 2011

Правильным способом является определение уникального индекса в базе данных и перехват исключения. Эти проверки в коде должны быть гораздо более сложными, чем простыми: скажи мне, если пользователь уже существует . Прежде всего, это не только проблема вставки, но пользователь также может изменить свою электронную почту. Еще одна проблема - параллелизм - в очень угловом случае два пользователя могут вставлять одни и те же записи одновременно. В обоих потоках тестовые запросы могут возвращать, что имя пользователя и адрес электронной почты не зарегистрированы, но во время сохранения один поток получит исключение (если у вас есть уникальный индекс в БД) или будет создана дублирующаяся запись. Если вы хотите избежать этого, вы должны заблокировать записи базы данных и таблицу блокировок для вставки (сериализуемая транзакция). Такая операция может снизить пропускную способность вашего приложения.

Другим фактом является то, что перед каждой вставкой вы будете выполнять 2 дополнительных запроса и по крайней мере один запрос перед каждым обновлением.

0 голосов
/ 02 апреля 2011

Разветвление ответа @ ysrb (с единственным методом, который вставляет пользователь), более надежное решение может заключаться в подключении к событию ObjectContext.SavingChanges и проведении там теста, если сущность UserсохраняетсяТаким образом, вы можете быть уверены, что ваша логика всегда срабатывает.

Пример:

        IEnumerable<ObjectStateEntry> changes = this.ObjectStateManager.GetObjectStateEntries(EntityState.Added);
        foreach (ObjectStateEntry stateEntryEntity in changes)
        {
            if (!stateEntryEntity.IsRelationship && stateEntryEntity.Entity != null)
            {
                if (stateEntryEntity.Entity is User)
                {
                    //Do you work here
                }
            }
        }
0 голосов
/ 02 апреля 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...