2

I am using linq to get some data from my database. When query is empty I want to throw an exception.

public class LinqDataBaseConnector : IDataBaseConnector
{
    public LinqDatabaseDataContext dataContext;

    public User getUser(string login, string password)
    {
        var query = (from c in dataContext.Users
                     where c.username == login && c.password == password
                     select c);

        if (query.Any())
        {
            return query.First();
        }
        else
        {
            throw new NullReferenceException("Empty query!");
        }
    }

    public HardwareConfiguration getHardwareConfiguration(int id)
    {
        var query = (from c in dataContext.HardwareConfigurations
                     where c.ID == id
                     select c);

        if (query.Any())
        {
            return query.First();
        }
        else
        {
            throw new NullReferenceException("Empty query!");
        }
    }
}

How to extract this if/else to ONE private method. Do I need to implement IQueryable<T> interface ?

6
  • 1
    The code, as you currently have it, is executing the query twice; one to see if it has any items, and once to actually get the first time. You probably don't want to do that. Commented Feb 11, 2015 at 19:53
  • 2
    Do not throw NullReferenceException instead throw InvalidArgumentException Commented Feb 11, 2015 at 19:54
  • query.First() will already throw an exception if the query is empty - why not just use that? Commented Feb 11, 2015 at 19:55
  • 1
    Additionally, uif you expect one and only one result, use Single() rather than First() Commented Feb 11, 2015 at 19:57
  • 3
    @rungus2 Which is exactly the behavior of First. Commented Feb 11, 2015 at 19:58

4 Answers 4

8

Don't call Any, just call First. It will throw an exception if the query has no items, which is exactly what you want. There's no need to create another operator as First already has the appropriate semantics.

In addition to just being easier, it results in the database query being executed just once, rather than twice.

Sign up to request clarification or add additional context in comments.

1 Comment

Seems to be fine now ;)
1

Simplified code below. Also i do hope you have some password hashing and not just plain text.

public class LinqDataBaseConnector : IDataBaseConnector
{
    #region Private Variables
    public LinqDatabaseDataContext dataContext;
    #endregion

    public User getUser(string login, string password)
    {   
        return this.dataContext.Users.First(x => x.username == login && x.password == password);
    }

    public HardwareConfiguration getHardwareConfiguration(int id)
    {   
        return this.dataContext.HardwareConfigurations.First(x => x.ID == id);
    }
}

Comments

0

Why not

    var query = (from c in dataContext.Users
                 where c.username == login && c.password == password
                 select c).FirstOrDefault();

    if (query!=null)
    {
        return query;
    }
    else
    {
        throw new NullReferenceException("Empty query!");
    }

1 Comment

As stated above no reason to throw an exception since First will throw if there is no results to the query its adding extra code the framework will already do.
0

Is there any reason why you cannot implement it as an extension method:

public static class Extensions
{
    public static T GetFirstOrException<T>(this IEnumerable<T> myList)
    {
        if (myList.Any())
        {
            return myList.First();
        }
        else
        {
            throw new NullReferenceException("Empty query!");
        }
    }
}

In both cases you can then use the extension method:

public User getUser(string login, string password)
{
    var query = (from c in dataContext.Users
                 where c.username == login && c.password == password
                 select c);

    return query.GetFirstOrException();
}

public HardwareConfiguration getHardwareConfiguration(int id)
{
    var query = (from c in dataContext.HardwareConfigurations
                 where c.ID == id
                 select c);

    return query.GetFirstOrException();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.