1

For my authentication model, I want to make sure that it is impossible for the same email to be registered more than once. I am new to both nHibernate and partially LINQ, so I am asking if this is adequate enough of a 'check' to ensure that happens.

  public MembershipCreateStatus CreateUser(string email, string password)
  {
   if (String.IsNullOrEmpty(email)) throw new ArgumentException("Value cannot be null or empty.", "userName");
   if (String.IsNullOrEmpty(password)) throw new ArgumentException("Value cannot be null or empty.", "password");


   using (var session = sessionFactory.OpenSession())
   {
    using (var transaction = session.BeginTransaction())
    {
     var members = session.CreateCriteria<Member>().List<Member>();

     // determine is the email address already exists in the database
     if (members.Any(i => i.Email == email))
      return MembershipCreateStatus.DuplicateEmail;

     // create the new member, if they are valid
     var member = new Member { Email = email };

     session.SaveOrUpdate(member);
     transaction.Commit();
    }
   }
   return MembershipCreateStatus.Success;
  }

Is there a more intelligent way of accomplishing this? I've had trouble with this in the past with a previous program (I used Linq to SQL on that one), and so I wanted to get some expert advice, this time around.

Femaref
  • 60,705
  • 7
  • 138
  • 176
Ciel
  • 17,312
  • 21
  • 104
  • 199
  • @Femaref: Not griping, but what did you change? I can't identify any changes. – Ciel Dec 10 '10 at 21:41
  • I don't necessarily know how to do so in NHibernate, but you need to ensure that the transaction you create is Serializable, so that a duplicate email address isn't inserted between the time that you check and the time that you perform your insert. – John Bledsoe Dec 10 '10 at 21:41
  • Stacey: formatting. Some of your code wasn't formatted as it wasn't indented properly. – Femaref Dec 10 '10 at 21:42
  • 4
    You should also add a unique constraint within your database to verify that your table never contains duplicate records. This will also help optimize database queries. – John Bledsoe Dec 10 '10 at 21:42
  • Hrnm. That makes sense... I've got no earthly idea how to do that, though. – Ciel Dec 10 '10 at 21:42

2 Answers2

7

What you're doing there is loading ALL members and querying the collection in memory.

This executes the query in the DB:

//this of course goes inside the transaction
if session.Query<Member>().Any(i => i.Email == email))
    return MembershipCreateStatus.DuplicateEmail;
Diego Mijelshon
  • 52,548
  • 16
  • 116
  • 154
  • Thanks, this is extremely useful. Querying it on the DB end will make it a lot faster. It was very difficult to pick which of the two answers to flag as the accepted one, since both were very helpful. I wish I could flag them both. – Ciel Dec 13 '10 at 18:28
  • That's fine; whatever works best for you should be the accepted answer :-) – Diego Mijelshon Dec 13 '10 at 18:40
4

Create a unique constraint as John said. You can figure out how to do that from this question:

SQL Server 2005 How Create a Unique Constraint?

That will ensure a duplicate never occurs.

Community
  • 1
  • 1
Phill
  • 18,398
  • 7
  • 62
  • 102