Tips: Better GetXXByYY in LINQ

book.anytao.com | Anytao in chinese 

Tips: Better GetXXByYY in LINQ

Published 22 Oct 2008, by Anytao
© 2008 Anytao.com, A fun world for making tech as art. 

I'm anytao, Visual C# MVP of Microsoft, and come from China.

Contents

Using LINQ for unifying the GetXXByYY in query expression.

 
Introduction

In a post Creating the Table Adapter Methods for GetUserByLogin, GetUserByUserName, and InsertUser, Nannette Thacker gives a good way to implement a table adapter for solving GetXXByYY in coding repeat works. Indeed, it’s very populating to implement the GetUserByName, GetUserByID, GetUserByEmail or ValidateUser and so on. So usually, you need to implement different services for UI calling, but there service basically has same implement process:

        public User GetUserByEmail(string email)
        {
            //Other implement to get DataContext and control DataLoadOption here
            //users = ...

            var user = (from u in users
                        where u.Email == email
                        select u).SingleOrDefault();

            return user;
        }

OK, if you need get user by ID, you should change your parameters and refresh a new query expression to retrieve your User data, you need implement more and more method for business logic, such as:

        public User GetUserByID(string id)
        { }

        public User GetUserByName(string id)
        { }

        public User GetUserByXX(string xx)
        { }

That’s boring and not effective at all. How can I use GetUser instead of all these methods?

Improvement by LINQ

Preparing with DataContext

In our case, it’s always getting data by DataContext. That is a typical operation in LINQ to SQL, so we ignore the details about how to generate a DataContext, but impelemt a query List by

            users.Add(new User { ID = "1", Email = "abc@live.com" });
            users.Add(new User { ID = "2", Email = "abc@hotmail.com" });
            users.Add(new User { ID = "3", Email = "mail@anytao.com" });

So, we will get user inforamation based on users context.

Using Expression Tree to build our query parameters

My friend Terry suggest another good tips to solve this problem by LINQ. LINQ has powerful magic to exceed your imagination. In our case, we can change our traditional ideas about query. Just think about Single or Find extension in .NET 3.0, we can also have our powerful feature here, like:

        public static User GetUser(Expression<Func<User, bool>> predicate)
        {
            //Other implement to get DataContext and control DataLoadOption here
            //users = ...
 
            IQueryable<User> query = users.AsQueryable<User>().Where(predicate);
 
            return query.Single() as User;
        }

Of course, that’s quite different from Single, because we have some other logic need to handle in GetUser method body. And Expression<Func<User, bool>> predicate will supply an valid expression by defining in a method accepting the lambda, that’s very magic like:

            User user = GetUser(u => u.ID == "1");
 
            User user2 = GetUser(u => u.Email == "mail@anytao.com");

Attention!

Func<User, bool> predicate can not be used here, because Func<User, bool> is not pure delegate to use in LINQ to SQL. Code below will give an runtime NullReferenceException,

       public static User GetUser(Func<User, bool> predicate)
        {
            //Other implement to get DataContext and control DataLoadOption here
            //users = db.GetTable<User>();
 
            var user = from u in users
                       where predicate(u)
                       select u;
 
            return user as User;
        }

How powerful it is.

 

Hope for helps.

Tao | Inside Necessary .NET

www.anytao.com  | Blog: http://anytao.cnblogs.com/

Tao Wang is Senior Developer working on a chinese company and responsible for project framework design, software develop and management. Tao is proficient with CLR Essential, good command of ASP.NET、ADO.NET、XML、SQL Server, and skilled in object-oriented, design pattern. Here is my new book about .NET inside book.anytao.com.

 

Reference

Using Lambda Expressions with LINQ to SQL

Dynamically Composing Expression Predicates

dynamic linq queries / dynamic where clause

© 2008 Anytao.com

This posting is provided "AS IS" with no warranties, and confers no rights.

5 Comments

  • good job!
    one question: how can I use 'users' in GetUser()?
    I don't think add extension method to the collection of users is a good idea.

  • @Ding Xue
    Most of suiation, users comes from DataContext and you can consider any other collection Entity.
    About extension method, I think your idea is right. In logic layer, you cann't supply service by the way of extension method. In our case, we change the traditional query way by lambda expersion. That makes sence.

  • Your Func example is flawed. The type returned by your LINQ query is IEnumerable, not User, so user As User will always return null.

  • @Joe Chung
    Of course, it's flawed. Do you take attention to my title above this example.

    ------------------------------
    Attention!

    Func predicate can not be used here, because Func is not pure delegate to use in LINQ to SQL. Code below will give an runtime NullReferenceException,

    ------------------------------

  • cool!

Comments have been disabled for this content.