Хорошо ли я справляюсь с соединениями с базой данных (Entity Framework)? - PullRequest
1 голос
/ 24 октября 2010

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

        public MembershipCreateStatus CreateUser(string username, string password, string mail,   bool autoemail, string fullname)
        {
            using (TemplateEntities ctx = new TemplateEntities())
            {
                using (TransactionScope tran = new TransactionScope())
                {
                    if (GetUser(username)!=null)
                        return MembershipCreateStatus.DuplicateUserName;
                    if (requiresUniqueEmail && !String.IsNullOrEmpty(GetUserNameByEmail(email)))
                        return MembershipCreateStatus.DuplicateEmail;                    
                    User userToCreate = new User
                    {
                        UserName=username,
                        PassWord=EncodePassword(password),
                        FullName=fullname,
                        Email=email,
                        AutoEmail=autoemail
                    };
                    try
                    {
                        ctx.Users.AddObject(userToCreate);
                        ctx.SaveChanges();
                        tran.Complete();
                        return MembershipCreateStatus.Success;
                    }
                    catch
                    {
                        return MembershipCreateStatus.UserRejected;
                    }
                }
            }
        }

        public override string GetUserNameByEmail(string email)
        {
            using (TemplateEntities ctx = new TemplateEntities())
            {
                return (from u in ctx.Users
                        where u.Email == email
                        select u.UserName).SingleOrDefault();
            }
        }

        public User GetUser(string username)
        {
            using (TemplateEntities ctx = new TemplateEntities())
            {
                return (from u in ctx.Users
                            where u.UserName == username
                            select u).FirstOrDefault();
            }
        }
  1. 1Q) Я открываю 3 соединения с базой данных.Это нормально?или у меня должно быть только одно соединение и как правильно управлять этим?
  2. 2Q) Нужна ли мне транзакция здесь и как правильно управлять этим?

1 Ответ

1 голос
/ 24 октября 2010

Re 3 соединения;Возможно, вы захотите, чтобы эти методы знали о контексте данных, либо передав его в качестве аргумента, либо используя частичные классы или методы расширения, чтобы добавить свой метод в контекст данных (предполагая, что этоодин и тот же тип контекста данных каждый раз).Это максимизирует повторное использование соединения и повторное использование идентификатора объекта.

Re транзакция;отправка уже должна быть транзакционной.Вопрос в том, нужны ли мне чтения в той же транзакции.И это зависит :) Зачастую это нормально, но вы можете получить проблемы с фантомным чтением и т. Д. Выполнение операций чтения внутри транзакции Serializable (как вы) гарантирует, что прочитанные данные неизменяйте до момента совершения транзакции.Однако это может отрицательно повлиять на пропускную способность (особенно, если участвует распределенная транзакция, отсюда и желание максимизировать повторное использование соединения) и (в некоторых случаях, если не выдается UPDLOCK) вводить дополнительные взаимоблокировки.компромисс.И это зависит от вашего конкретного сценария.

В качестве примера переписывания тех, которые передаются в контексте:

public override string GetUserNameByEmail(TemplateEntities ctx, string email)
{
    return (from u in ctx.Users
            where u.Email == email
            select u.UserName).SingleOrDefault();
}

public User GetUser(TemplateEntities ctx, string username)
{
    return (from u in ctx.Users
            where u.UserName == username
            select u).FirstOrDefault();
}

И теперь вы можете передать в своем контексте;возможно, вы могли бы перегружать метод, если хотите по-прежнему предлагать его как опцию, не передавая явно контекст:

public User GetUser(string username)
{
    using(var ctx = new TemplateEntities()) { return GetUser(ctx, username);}
}
...