Martin Heller
Contributing Writer

LINQ Queries Follow-up

analysis
Jan 28, 20082 mins

When I was writing my review of Visual Studio 2008, I built a little console application that generated JavaScript data structures from a SQL Server 2000 database in C#, using LINQ to SQL. As I mentioned in the review, I never did figure out how to write the LINQ equivalent of a SQL "SELECT DISTINCT" query. In reading the LINQ section of C# 3.0 in a Nutshell*, I have come to realize that the LINQ code

When I was writing my review of Visual Studio 2008, I built a little console application that generated JavaScript data structures from a SQL Server 2000 database in C#, using LINQ to SQL. As I mentioned in the review, I never did figure out how to write the LINQ equivalent of a SQL “SELECT DISTINCT” query.

In reading the LINQ section of C# 3.0 in a Nutshell*, I have come to realize that the LINQ code I wrote for that little project was basically SQL translated literally to LINQ. I might have done it quite differently if I had been thinking directly in LINQ.

Here’s the meat of the program:

using(pcpDataClasses1DataContext db=new pcpDataClasses1DataContext())

{

    //Generate AVInfo

    string category1 = “AntiVirus”;

    string category2 = “AntiSpyware”;

    bool init = false;

    var qAV = from ai in db.AppInfos

              join acai in db.AppCatAIs on ai.Prodid equals acai.Prodid

              join ac in db.AppCategories on acai.acatid equals ac.acatid

              where ac.Category == category1 || ac.Category== category2

              orderby ai.ProductName

              select ai;

    //Beginning of JS structure

    Console.WriteLine(“var AMInfo = [“);

    //Per-item entries

    string fmt = “{{nProdid: {0},nName: “{1}”,nInst: [ {2} ],nRoot: “{3}”,nSigs: “{4}”,nInit: {5},nNeedRoot: {6}n}}”;

    foreach (AppInfo a in qAV)

    {

        if (init)

            Console.Write(“,”);

        Console.WriteLine(fmt, a.Prodid, a.ProductName, a.InstPattern, a.Root, a.Sigs,

            String.IsNullOrEmpty(a.InitMethod) ? “null” : a.InitMethod, a.NeedRoot.ToString().ToLower());

        if (!init)

            init = true;

    }

    //finish it off

    Console.WriteLine(“]”);

}

The O-R diagram for the database tables being queried is here.

How would you rewrite this to (1) emit only distinct items, and (2) be more like idiomatic LINQ and less like translated SQL?

*In my posting on Books for Learning C# 3.0 I said that I didn’t yet have a copy of the C# 3.0 Nutshell book. I’m embarrassed to admit that I did have it: it was hiding in a big stack of books.

Martin Heller

Martin Heller is a contributing writer at InfoWorld. Formerly a web and Windows programming consultant, he developed databases, software, and websites from his office in Andover, Massachusetts, from 1986 to 2010. From 2010 to August of 2012, Martin was vice president of technology and education at Alpha Software. From March 2013 to January 2014, he was chairman of Tubifi, maker of a cloud-based video editor, having previously served as CEO.

Martin is the author or co-author of nearly a dozen PC software packages and half a dozen Web applications. He is also the author of several books on Windows programming. As a consultant, Martin has worked with companies of all sizes to design, develop, improve, and/or debug Windows, web, and database applications, and has performed strategic business consulting for high-tech corporations ranging from tiny to Fortune 100 and from local to multinational.

Martin’s specialties include programming languages C++, Python, C#, JavaScript, and SQL, and databases PostgreSQL, MySQL, Microsoft SQL Server, Oracle Database, Google Cloud Spanner, CockroachDB, MongoDB, Cassandra, and Couchbase. He writes about software development, data management, analytics, AI, and machine learning, contributing technology analyses, explainers, how-to articles, and hands-on reviews of software development tools, data platforms, AI models, machine learning libraries, and much more.

More from this author