Click here to Skip to main content
15,892,005 members
Articles / Programming Languages / C# 4.0

Dynamically evaluated SQL LINQ queries

Rate me:
Please Sign up or sign in to vote.
4.95/5 (35 votes)
30 Nov 2013CPOL8 min read 193.5K   2.6K   116  
Extension methods to evaluate plain text SQL queries against IEnumerable collections.
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace SqlLinq.UnitTests
{
    [TestClass]
    public class JoinTests
    {
        [TestMethod]
        public void JoinObjects()
        {
            IEnumerable<Person> source = TestData.GetPeople();
            IEnumerable<Family> families = TestData.GetFamilies();

            var answer = from p in source
                         join f in families on p.Address equals f.Address
                         select new FamilyMember { Name = p.Name, LastName = f.Name, Location = p.Address };

            var result = source.Query<Person, Family, FamilyMember>("SELECT Name, that.Name AS LastName, Address AS Location FROM this INNER JOIN that ON this.Address = that.Address", families);

            Assert.IsTrue(result.Any());
            Assert.IsTrue(answer.Any());
            Assert.IsTrue(result.SequenceEqual(answer));
        }

        [TestMethod]
        public void JoinAndGroup()
        {
            IEnumerable<Person> source = TestData.GetPeople();
            IEnumerable<Family> families = TestData.GetFamilies();

            var answer = from p in source
                         join f in families on p.Address equals f.Address
                         group f by f.Name into g
                         select new Tuple<string, int>(g.Key, g.Count());

            var result = source.Query<Person, Family, Tuple<string, int>>("SELECT that.Name, COUNT(*) FROM this INNER JOIN that ON this.Address = that.Address GROUP BY that.Name", families);

            Assert.IsTrue(result.Any());
            Assert.IsTrue(answer.Any());
            Assert.IsTrue(result.SequenceEqual(answer));
        }

        [TestMethod]
        public void JoinAndGroupAndOrder()
        {
            IEnumerable<Person> source = TestData.GetPeople();
            IEnumerable<Family> families = TestData.GetFamilies();

            var answer = from p in source
                         join f in families on p.Address equals f.Address
                         group f by f.Name into g
                         orderby g.Key descending
                         select new Tuple<string, int>(g.Key, g.Count());
                         

            var result = source.Query<Person, Family, Tuple<string, int>>("SELECT that.Name, COUNT(*) FROM this INNER JOIN that ON this.Address = that.Address GROUP BY that.Name ORDER BY that.Name DESC", families);

            Assert.IsTrue(result.Any());
            Assert.IsTrue(answer.Any());
            Assert.IsTrue(result.SequenceEqual(answer));
        }
        [TestMethod]
        public void JoinObjectsIntoDictionary()
        {
            IEnumerable<Person> source = TestData.GetPeople();
            IEnumerable<Family> families = TestData.GetFamilies();

            var answer = from p in source
                         join f in families on p.Address equals f.Address
                         select new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase)
                         { 
                            {"Name", p.Name},
                            {"LastName", f.Name},
                            {"Location", p.Address}
                         };

            var result = source.Query<Person, Family, IDictionary<string, object>>("SELECT Name, that.Name AS LastName, Address AS Location FROM this INNER JOIN that ON this.Address = that.Address", families);

            Assert.IsTrue(result.Any());
            Assert.IsTrue(answer.Any());
            Assert.IsTrue(result.SequenceEqual(answer, new DictionaryComparer<string, object>()));
        }

        [TestMethod]
        public void JoinDictionaries()
        {
            IEnumerable<IDictionary<string, object>> outer = TestData.GetPeopleDictionary();
            IEnumerable<IDictionary<string, object>> inner = TestData.GetFamiliesDictionary();

            var answer = from p in outer
                         join f in inner on p["lastName"] equals f["familyName"]
                         select new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase) 
                         {
                             {"Name", p["name"] },            
                             {"lastName", p["lastName"] },
                             {"city", f["city"] }
                         };

            var result = outer.Query<IDictionary<string, object>, IDictionary<string, object>, IDictionary<string, object>>("SELECT Name, lastName, city FROM this INNER JOIN that ON this.lastName = that.familyName", inner);
           
            Assert.IsTrue(result.Any());
            Assert.IsTrue(answer.Any());
            Assert.IsTrue(result.SequenceEqual(answer, new DictionaryComparer<string, object>()));
        }

        [TestMethod]
        public void JoinDictionariesIntoObject()
        {
            IEnumerable<IDictionary<string, object>> outer = TestData.GetPeopleDictionary();
            IEnumerable<IDictionary<string, object>> inner = TestData.GetFamiliesDictionary();

            var answer = from p in outer
                         join f in inner on p["lastName"] equals f["familyName"]
                         select new FamilyMember { Name = p["name"].ToString(), LastName = f["familyName"].ToString(), Location = f["city"].ToString() };


            var result = outer.Query<IDictionary<string, object>, IDictionary<string, object>, FamilyMember>("SELECT Name, lastName, city AS Location FROM this INNER JOIN that ON this.lastName = that.familyName", inner);

            Assert.IsTrue(result.Any());
            Assert.IsTrue(answer.Any());
            Assert.IsTrue(result.SequenceEqual(answer));
        }

        [TestMethod]
        public void JoinDictionariesIntoTuple()
        {
            IEnumerable<IDictionary<string, object>> outer = TestData.GetPeopleDictionary();
            IEnumerable<IDictionary<string, object>> inner = TestData.GetFamiliesDictionary();

            var answer = from p in outer
                         join f in inner on p["lastName"] equals f["familyName"]
                         select new Tuple<string, string, string>(p["name"].ToString(), f["familyName"].ToString(), f["city"].ToString());


            var result = outer.Query<IDictionary<string, object>, IDictionary<string, object>, Tuple<string, string, string>>("SELECT Name, lastName, city AS Location FROM this INNER JOIN that ON this.lastName = that.familyName", inner);

            Assert.IsTrue(result.Any());
            Assert.IsTrue(answer.Any());
            Assert.IsTrue(result.SequenceEqual(answer));
        }

        [TestMethod]
        public void JoinDictionaryToObjects()
        {
            IEnumerable<IDictionary<string, object>> outer = TestData.GetPeopleDictionary();

            IEnumerable<Family> inner = TestData.GetFamilies();

            var answer = from p in outer
                         join f in inner on p["lastName"] equals f.Name
                         select new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase) 
                         {
                             {"Name", p["name"] },            
                             {"lastName", p["lastName"] },
                             {"Address", f.Address }
                         };

            var result = outer.Query<IDictionary<string, object>, Family, IDictionary<string, object>>("SELECT Name, lastName, Address FROM this INNER JOIN that ON this.lastName = that.Name", inner);
            
            Assert.IsTrue(result.Any());
            Assert.IsTrue(answer.Any());
            Assert.IsTrue(result.SequenceEqual(answer, new DictionaryComparer<string, object>()));
        }

        [TestMethod]
        public void JoinObjectsToDictionary()
        {
            IEnumerable<Family> outer = TestData.GetFamilies();
            IEnumerable<IDictionary<string, object>> inner = TestData.GetPeopleDictionary();

            var answer = from f in outer
                         join p in inner on f.Name equals p["lastName"]
                         select new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase) 
                         {
                             {"Name", p["name"] },            
                             {"lastName", p["lastName"] },
                             {"Address", f.Address }
                         };

            var result = outer.Query<Family, IDictionary<string, object>, IDictionary<string, object>>("SELECT that.Name, that.lastName, Address FROM this INNER JOIN that ON this.Name = that.lastName", inner);

            Assert.IsTrue(result.Any());
            Assert.IsTrue(answer.Any()); 
            Assert.IsTrue(result.SequenceEqual(answer, new DictionaryComparer<string, object>()));
        }

        [TestMethod]
        public void OrderedJoin()
        {
            IEnumerable<Person> source = TestData.GetPeople();
            IEnumerable<Family> families = TestData.GetFamilies();

            var answer = source.Join<Person, Family, string, FamilyMember>(families, p => p.Address, f => f.Address,
                (p, f) => new FamilyMember { Name = p.Name, LastName = f.Name, Location = f.Address }).OrderByDescending(m => m.Location);

            var result = source.Query<Person, Family, FamilyMember>("SELECT Name, that.Name AS LastName, Address AS Location FROM this INNER JOIN that ON this.Address = that.Address ORDER BY Address DESC", families);

            Assert.IsTrue(result.Any());
            Assert.IsTrue(answer.Any());
            Assert.IsTrue(result.SequenceEqual(answer));
        }

        [TestMethod]
        public void JoinWithWhere()
        {
            IEnumerable<Person> source = TestData.GetPeople();
            IEnumerable<Family> families = TestData.GetFamilies();
            var answer = from p in source
                    join f in families on p.Address equals f.Address
                    where p.Address == "401 Main St., St. Paul, MN 55132"
                    select new FamilyMember { Name = p.Name, LastName = f.Name, Location = f.Address };

            var result = source.Query<Person, Family, FamilyMember>("SELECT this.Name, that.Name AS LastName, Address AS Location FROM this INNER JOIN that ON this.Address = that.Address WHERE this.Address = '401 Main St., St. Paul, MN 55132'", families);

            Assert.IsTrue(result.Any());
            Assert.IsTrue(answer.Any());
            Assert.IsTrue(result.SequenceEqual(answer));
        }

        [TestMethod]
        public void JoinWithInnerWhere2()
        {
            IEnumerable<Person> source = TestData.GetPeople();
            IEnumerable<Family> families = TestData.GetFamilies();
            var answer = from p in source
                         join f in families on p.Address equals f.Address
                         where f.Name == "Smith"
                         select new FamilyMember { Name = p.Name, LastName = f.Name, Location = f.Address };

            var result = source.Query<Person, Family, FamilyMember>("SELECT Name, that.Name AS LastName, Address AS Location FROM this INNER JOIN that ON this.Address = that.Address WHERE that.Name = 'Smith'", families);

            Assert.IsTrue(answer.Any());       
            Assert.IsTrue(result.Any());
            Assert.IsTrue(result.SequenceEqual(answer));
        }

        [TestMethod]
        public void JoinWithThisAsKey()
        {
            BasicPerson magnus = new BasicPerson { Name = "Hedlund, Magnus" };
            BasicPerson terry = new BasicPerson { Name = "Adams, Terry" };
            BasicPerson charlotte = new BasicPerson { Name = "Weiss, Charlotte" };

            Pet barley = new Pet { Name = "Barley", Owner = terry };
            Pet boots = new Pet { Name = "Boots", Owner = terry };
            Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte };
            Pet daisy = new Pet { Name = "Daisy", Owner = magnus };

            List<BasicPerson> people = new List<BasicPerson> { magnus, terry, charlotte };
            List<Pet> pets = new List<Pet> { barley, boots, whiskers, daisy };

            // Create a list of Person-Pet pairs where 
            // each element is an anonymous type that contains a
            // Pet's name and the name of the Person that owns the Pet.
            var answer =
                people.Join<BasicPerson, Pet, BasicPerson, Pair>(pets,
                            person => person,
                            pet => pet.Owner,
                            (person, pet) =>
                                new Pair { OwnerName = person.Name, PetName = pet.Name });

            var result = people.Query<BasicPerson, Pet, Pair>("SELECT this.Name AS OwnerName, that.Name AS PetName FROM this INNER JOIN that ON this = that.Owner", pets);

            Assert.IsTrue(result.Any());
            Assert.IsTrue(answer.Any());
            Assert.IsTrue(result.SequenceEqual(answer));
        }


        [TestMethod]
        public void JoinWithThisAsKeyTuple()
        {
            BasicPerson magnus = new BasicPerson { Name = "Hedlund, Magnus" };
            BasicPerson terry = new BasicPerson { Name = "Adams, Terry" };
            BasicPerson charlotte = new BasicPerson { Name = "Weiss, Charlotte" };

            Pet barley = new Pet { Name = "Barley", Owner = terry };
            Pet boots = new Pet { Name = "Boots", Owner = terry };
            Pet whiskers = new Pet { Name = "Whiskers", Owner = charlotte };
            Pet daisy = new Pet { Name = "Daisy", Owner = magnus };

            List<BasicPerson> people = new List<BasicPerson> { magnus, terry, charlotte };
            List<Pet> pets = new List<Pet> { barley, boots, whiskers, daisy };

            // Create a list of Person-Pet pairs where 
            // each element is an anonymous type that contains a
            // Pet's name and the name of the Person that owns the Pet.
            var answer =
                people.Join<BasicPerson, Pet, BasicPerson, Tuple<string, string>>(pets,
                            person => person,
                            pet => pet.Owner,
                            (person, pet) =>
                                new Tuple<string, string>(person.Name, pet.Name));

            var result = people.Query<BasicPerson, Pet, Tuple<string, string>>("SELECT this.Name AS OwnerName, that.Name AS PetName FROM this INNER JOIN that ON this = that.Owner", pets);

            Assert.IsTrue(result.Any());
            Assert.IsTrue(answer.Any());
            Assert.IsTrue(result.SequenceEqual(answer));
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Team Leader Starkey Laboratories
United States United States
The first computer program I ever wrote was in BASIC on a TRS-80 Model I and it looked something like:
10 PRINT "Don is cool"
20 GOTO 10

It only went downhill from there.

Hey look, I've got a blog

Comments and Discussions