.NET Forum / Languages / C# / March 2008
LINQ and SQL in general.
|
|
Thread rating:  |
Alcides - 27 Feb 2008 17:56 GMT Hello all,
I learn about LINQ here in this forum. I been a VB.NET programmer for quite a while and we are using an internal solution for SQL access. I have some experience with C# and I started to write a blog to share my experiences with a sql framework. I would like to hear some opinions about LINQ, is it the main thing when accessing sql now? what are the main advantages/disavantages using it. Nothing fancy, just drop a few lines about it... I read some material but I want to hear the opinion from the field. I'll be glad to share experience in this area.
Thanks in advance.
Alcides (http://alsql.blogspot.com/).
Cowboy (Gregory A. Beamer) - 27 Feb 2008 18:41 GMT LINQ is most useful, to me, for easily iterating through objects that use IEnumerable. This includes sql constructs created by using LINQ to SQL queries, but it is equally useful, if not more so, for generically querying sets of objects, etc.
LINQ itself is good for the average web scenario, but can fall flat on high performance, high load applications. Anything where you have to grab large amounts of data before a save is not best done with LINQ, for example.
Overall, if you do not think of LINQ as data access, it is a good thing. When you start thinking of it as a transport "layer", you can end up making some bad decisions.
 Signature Gregory A. Beamer MVP, MCP: +I, SE, SD, DBA
*************************************************
| Think outside the box! *************************************************
> Hello all, > [quoted text clipped - 11 lines] > > Alcides (http://alsql.blogspot.com/). Michel Walsh - 27 Feb 2008 18:45 GMT The main advantage I see is that it can simplify the interfacing between a database (hierarchy model) and the code (object model).
The big disadvantage is that it is much more complex than SQL to define JOIN or complex expressions, as when many tables are involved. So, LINQ would probably be limited to 'query' involving very few tables, or to view/function stored into the database where the complexity is pre-defined using SQL.
Vanderghast, Access MVP
> Hello all, > [quoted text clipped - 11 lines] > > Alcides (http://alsql.blogspot.com/). Stefan Nobis - 27 Feb 2008 22:32 GMT > The main advantage I see is that it can simplify the interfacing > between a database (hierarchy model) and the code (object model). Hierachical databases are from the 70ties and in many use cases do have much more disadvantages than advantages. Todays DBMS like MS SQL, Oracle, PostgreSQL etc. are some kind of misguided relational systems (SQL in many many cases contradicts the relational model and tears quite some holes in it). BTW XML is a hierachical model (so quite 70ties, not very modern :)).
 Signature Stefan.
Frans Bouma [C# MVP] - 28 Feb 2008 08:37 GMT > The main advantage I see is that it can simplify the interfacing > between a database (hierarchy model) and the code (object model). You ment 'relational model' ? There's nothing hierarchical about a relational model.
> The big disadvantage is that it is much more complex than SQL to > define JOIN or complex expressions, as when many tables are involved. not necessarily. Perhaps left joins, but joins in general are pretty straight forward (as in, same keywords as SQL)
> So, LINQ would probably be limited to 'query' involving very few > tables, or to view/function stored into the database where the > complexity is pre-defined using SQL. Can you show an example where the SQL query is simpler than the Linq query?
FB
> Vanderghast, Access MVP > [quoted text clipped - 14 lines] > > > > Alcides (http://alsql.blogspot.com/).
 Signature ------------------------------------------------------------------------ Lead developer of LLBLGen Pro, the productive O/R mapper for .NET LLBLGen Pro website: http://www.llblgen.com My .NET blog: http://weblogs.asp.net/fbouma Microsoft MVP (C#) ------------------------------------------------------------------------
Michel Walsh - 28 Feb 2008 11:48 GMT You are right, I meant relational !
An example? sure. Either a group by with conditions (note the b.kindOf can be re-written as a WHERE clause, here)
SELECT a.myGroup, SUM(b.myValue) FROM myTable AS a INNER JOIN myReference AS b ON a.someID = b.refID AND b.kindOf= 1 GROUP BY a.myGroup HAVING MIN(b.myValue) >0;
either a ranking (non-equi join)
SELECT a.state, COUNT(*) AS rank FROM myTable AS a INNER JOIN myTable AS b ON a.population <= b.population GROUP BY a.state
which rank each state in accordance with their population.
Even a simple translation:
SELECT a.cityName, COALESCE(b.cityname, a.cityName) FROM cities AS a LEFT JOIN translations AS b ON a.cityID=b.cityID
such as 'Byzance' and 'Constantinople' are translated as 'Istanbul, but 'Brasilia, having no match in table translations, stays 'Brasilia. Thanks thanks to COALESCE, it would be arguably as simple as SQL, in LINQ.
These queries are not elementary, sure, but they do not involve correlated sub-query either, and only 2 tables.
Vanderghast, Access MVP
>> The main advantage I see is that it can simplify the interfacing >> between a database (hierarchy model) and the code (object model). [quoted text clipped - 35 lines] >> > >> > Alcides (http://alsql.blogspot.com/). Jon Skeet [C# MVP] - 28 Feb 2008 13:22 GMT > You are right, I meant relational ! > [quoted text clipped - 6 lines] > GROUP BY a.myGroup > HAVING MIN(b.myValue) >0; That's a groupby followed by a where, as far as I can tell, then select with a Sum involved.
> either a ranking (non-equi join) > [quoted text clipped - 4 lines] > > which rank each state in accordance with their population. Multiple "from" clauses and a "where" clause.
> Even a simple translation: > [quoted text clipped - 5 lines] > 'Brasilia, having no match in table translations, stays 'Brasilia. Thanks > thanks to COALESCE, it would be arguably as simple as SQL, in LINQ. I don't know whether using the null coalescing operator in C# will get translated into a COALESCE in SQL or not, but it's worth a try.
I haven't tried any of the above - and there may well be subtleties I'm missing - but I personally find LINQ queries *easier* to read because the flow is always "top to bottom". The logical flow in SQL jumps around all over the place.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet World class .NET training in the UK: http://iterativetraining.co.uk
Michel Walsh - 28 Feb 2008 14:42 GMT I must add that we generally starts with a problem, then have to find a solution, in terms of writing in SQL or in LINQ code. Translation from SQL to LINQ is a little bit artificial. As example, the problem is NOT about to translate:
SELECT a.workerID FROM workersSkills AS a INNER JOIN requiredSkills AS b ON a.skillID=b.skillID GROUP BY a.workerID HAVING COUNT(*) = (SELECT COUNT(*) FROM requiredSkills)
into LINQ, but to find the workers having all the required skills. I STRONGLY suspect someone using LINQ will come with some "for each worker", get a list of his skills, loop through the required skills list, to see it they are all contains in the list of skills for the actual worker we just got, and if so, keep the workerID in a 'result list'. So, yes, that procedure will be easier to follow, but how many people will need to 'follow' it once it is working? And, it seems to me, the LINQ solution will be based on simple SQL statements, rather than on ONE, more complex, statement, but as far as the whole problem has to be solved, the LINQ solution would be clearly more verbose, because LINQ does not 'lead' culturally to solve a problem in 'one step' ?
Note that I don't say in any way that SQL is a simple language. You don't come naturally with the solution above first hour you learn SQL, unless you are really a genius. But as time passes, you see the 'patterns' as naturally as a 'for each' loop.
By the way, another great advantage to LINQ: it allows you to write a query against a database where, in theory, you can be forbidden to write any query (by some administrative politic).
Vanderghast, Access MVP
>> You are right, I meant relational ! >> [quoted text clipped - 39 lines] > the flow is always "top to bottom". The logical flow in SQL jumps > around all over the place. Jon Skeet [C# MVP] - 28 Feb 2008 15:00 GMT > I must add that we generally starts with a problem, then have to find a > solution, in terms of writing in SQL or in LINQ code. Translation from SQL [quoted text clipped - 12 lines] > they are all contains in the list of skills for the actual worker we just > got, and if so, keep the workerID in a 'result list'. I would certainly hope that's not the case. It may be until people actually get used to LINQ - but when devs get more used to thinking in queries, I would hope they'd do the right thing.
The above is reasonably easy to express in a single LINQ query. Of course, there are several different ways of solving the problem, even within a single SQL or LINQ query.
> So, yes, that > procedure will be easier to follow, but how many people will need to [quoted text clipped - 3 lines] > solution would be clearly more verbose, because LINQ does not 'lead' > culturally to solve a problem in 'one step' ? Why do you believe that LINQ doesn't lead to the solution being a single step? I'd say it does, if you really go for idiomatic LINQ.
> Note that I don't say in any way that SQL is a simple language. You don't > come naturally with the solution above first hour you learn SQL, unless you > are really a genius. But as time passes, you see the 'patterns' as naturally > as a 'for each' loop. Ditto LINQ, I'd say.
> By the way, another great advantage to LINQ: it allows you to write a query > against a database where, in theory, you can be forbidden to write any query > (by some administrative politic). Not sure what you mean by that, to be honest.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet World class .NET training in the UK: http://iterativetraining.co.uk
Michel Walsh - 28 Feb 2008 15:19 GMT >> By the way, another great advantage to LINQ: it allows you to write a >> query [quoted text clipped - 3 lines] > > Not sure what you mean by that, to be honest. I mixed two concepts. Once you got the data, locally, you can probably use LINQ to objects to query the objects, without using the database at all, without using LINQ to database, in case the admin do not allow your access to run (write) ad hoc query, on the database (even if they are not action query).
Vanderghast, Access MVP
Jon Skeet [C# MVP] - 28 Feb 2008 15:25 GMT On Feb 28, 3:19 pm, "Michel Walsh" <vanderghastArobaseMsnDot...@nospam.com> wrote:
> >> By the way, another great advantage to LINQ: it allows you to write a > >> query [quoted text clipped - 9 lines] > to run (write) ad hoc query, on the database (even if they are not action > query). Ah, right. Yes, that's certainly possible - while somewhat inefficient compared with doing it in the database, of course :)
Jon
Cowboy (Gregory A. Beamer) - 28 Feb 2008 15:41 GMT You can simplify a bit more if you move away from LINQ queries and move more into lambda expressions. The query syntax sometimes paints you into a box, and there are a few cases where you have to use lambda expressions to create the syntax you desire, no matter how you try to create the query.
 Signature Gregory A. Beamer MVP, MCP: +I, SE, SD, DBA
*************************************************
| Think outside the box! *************************************************
> The main advantage I see is that it can simplify the interfacing between a > database (hierarchy model) and the code (object model). [quoted text clipped - 22 lines] >> >> Alcides (http://alsql.blogspot.com/). Jon Skeet [C# MVP] - 28 Feb 2008 16:11 GMT On Feb 28, 3:41 pm, "Cowboy \(Gregory A. Beamer\)" <NoSpamMgbwo...@comcast.netNoSpamM> wrote:
> You can simplify a bit more if you move away from LINQ queries and move more > into lambda expressions. The query syntax sometimes paints you into a box, > and there are a few cases where you have to use lambda expressions to create > the syntax you desire, no matter how you try to create the query. Agreed. This is one of the places where it's nice to know what the query expression is translated into, so that if you've got a query expression which you want to modify just a bit (but in a way which the query expression syntax doesn't directly allow) you can build the non- q.e. code first and then change it.
I wonder if Resharper 4.0 will have that as a refactoring... it would be very neat.
Jon
Alcides - 28 Feb 2008 17:06 GMT Interesting discussion, it seems linq syntax can get very complex, naturaly due to complexity of the sql query you are building. If your application have a lot of complex queries, all the time, may not be the appropiate solution, I wonder what would be?
But looks like linq can be handle most requests for a standard aplication, I mean, leaving complex queries to the reports team (using crystal reports, views and store procedures). Am I right?
Jon Skeet [C# MVP] - 28 Feb 2008 18:44 GMT > Interesting discussion, it seems linq syntax can get very complex, > naturaly due to complexity of the sql query you are building. Well, due to the complexity of the query you wish to perform. Don't forget that LINQ doesn't just target SQL.
> If your > application have a lot of complex queries, all the time, may not be > the appropiate solution, I wonder what would be? I don't know why you'd think LINQ would be inappropriate for complex queries. If the complexity has to be *somewhere*, I'm happy for it to be in C# personally.
> But looks like linq can be handle most requests for a standard > aplication, I mean, leaving complex queries to the reports team (using > crystal reports, views and store procedures). Am I right? Well, in some cases a view or stored proc could make sense - but given that the complexity has to be somewhere, it may well be just as sensible to do it in the LINQ layer as anywhere else.
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet World class .NET training in the UK: http://iterativetraining.co.uk
Alcides - 28 Feb 2008 19:05 GMT > > Interesting discussion, it seems linq syntax can get very complex, > > naturaly due to complexity of the sql query you are building. [quoted text clipped - 21 lines] > Jon Skeet - <sk...@pobox.com>http://www.pobox.com/~skeet Blog:http://www.msmvps.com/jon.skeet > World class .NET training in the UK:http://iterativetraining.co.uk I got you point. If the query is complex, there's no easy solution. So keeping that logic in linq/C# make sense.
Christopher Van Kirk - 29 Feb 2008 04:25 GMT I thought it was interesting too, but I did some analysis and it performs like a dog. They'll need to tweak it alot before it's useful in the real world, I think.
Nice idea though.
>Hello all, > [quoted text clipped - 11 lines] > >Alcides (http://alsql.blogspot.com/).
 Signature Posted via a free Usenet account from http://www.teranews.com
Jon Skeet [C# MVP] - 29 Feb 2008 07:36 GMT > I thought it was interesting too, but I did some analysis and it > performs like a dog. They'll need to tweak it alot before it's useful > in the real world, I think. I suspect you were doing something wrong if it was performing badly for you - or at least, there may well have been simple ways to fix the issue. Can you give details?
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet World class .NET training in the UK: http://iterativetraining.co.uk
Frans Bouma [C# MVP] - 29 Feb 2008 08:50 GMT > > I thought it was interesting too, but I did some analysis and it > > performs like a dog. They'll need to tweak it alot before it's [quoted text clipped - 3 lines] > for you - or at least, there may well have been simple ways to fix > the issue. Can you give details? var q = from c in nw.Customers select new { c.Country, Orders = from o in nw.Orders where o.CustomerID = c.CustomerID select new { o.OrderID OrderDetails = from od in nw.OrderDetails where od.OrderID = o.OrderID select od } };
It takes roughly a second to fetch this little graph using linq to sql as it executes every nested query on the fly so this leads to: 1 + (#customers) + (#orders) amount of queries.
It can be done in 3 queries. It takes some in-memory lambda creation/compilation, derived table voodoo, but it's doable. :) (I'm almost done with my implementation of this, will blog about it soon)
With loadoptions etc. it's the same thing: they can't deal with multi-part edges because they use a join of Parent + children to fetch parent + children. But that's not the way to do it. Fetch children based on filter on parent, then either use hashes and a merger or in-memory compiled lambda expressions to merge the rows.
Sure, for flat sets, it's ok to some extend, however with nested sets, it falls flat on its face, hard. Which is odd, considering the fact that MS had 'spans' already in objectspaces (although their implementation in that framework also sucked)
FB
 Signature ------------------------------------------------------------------------ Lead developer of LLBLGen Pro, the productive O/R mapper for .NET LLBLGen Pro website: http://www.llblgen.com My .NET blog: http://weblogs.asp.net/fbouma Microsoft MVP (C#) ------------------------------------------------------------------------
Jon Skeet [C# MVP] - 29 Feb 2008 09:03 GMT > > > I thought it was interesting too, but I did some analysis and it > > > performs like a dog. They'll need to tweak it alot before it's [quoted text clipped - 22 lines] > as it executes every nested query on the fly so this leads to: > 1 + (#customers) + (#orders) amount of queries. Right. Definitely bad. I'm certainly not trying to defend LINQ to SQL as great in all respects - it's definitely a "v1" product, for starters.
However, I think that Christopher's *blanket* statement of "it performs like a dog" is *way* too general. If he'd said, "I found some situations where it executed more queries than I wanted, and I couldn't work out a way to fix that" it would have been a much more reasonable statement.
> It can be done in 3 queries. It takes some in-memory lambda > creation/compilation, derived table voodoo, but it's doable. :) (I'm > almost done with my implementation of this, will blog about it soon) Of course, in the above case you could probably get away with fetching all the necessary fields from all the rows of the appropriate tables, then joining it all up in memory. Not so each when you only want particular rows though :)
> With loadoptions etc. it's the same thing: they can't deal with > multi-part edges because they use a join of Parent + children to fetch [quoted text clipped - 6 lines] > that MS had 'spans' already in objectspaces (although their > implementation in that framework also sucked) Does the Entity Framework do any better on this, do you know?
 Signature Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet World class .NET training in the UK: http://iterativetraining.co.uk
Frans Bouma [C# MVP] - 01 Mar 2008 10:05 GMT > > > > I thought it was interesting too, but I did some analysis and it > > > > performs like a dog. They'll need to tweak it alot before it's [quoted text clipped - 26 lines] > as great in all respects - it's definitely a "v1" product, for > starters. Don't buy the 'it's a v1 product' excuse! It's not a v1 product, it's taken them a couple of previous attempts to get this far, so I don't see how this can be a v1 product. Then again, there are enough examples out there which prove that it can be done without a lot of hassle so why they didn't implement it is beyond me.
> > It can be done in 3 queries. It takes some in-memory lambda > > creation/compilation, derived table voodoo, but it's doable. :) (I'm [quoted text clipped - 4 lines] > appropriate tables, then joining it all up in memory. Not so each > when you only want particular rows though :) every nested set is a query on its own. You can obtain a correlation filter in the nested set and use that with an EXISTS query or IN query on the parent set :) This limits the nested set on the rows related to parents you've fetched. You can then either build an in-memoryh lambda to compare rows or build 2 hash sets and compare hashes.
What's odd is that this is the way you have to do eager loading anyway, so they have written the code already. At least, more or less (as their eager loading code isn't up to par)
> > With loadoptions etc. it's the same thing: they can't deal with > > multi-part edges because they use a join of Parent + children to [quoted text clipped - 8 lines] > > Does the Entity Framework do any better on this, do you know? I don't know about the nested sets in projections, probably not. They do have an '.Include()' extension method if I'm not mistaken which allows you to specify related entities to fetch inside the query, using eager loading. I'm not sure how they'll do that though (i.e. with the same approach as linq to sql or with a better approach).
FB
 Signature ------------------------------------------------------------------------ Lead developer of LLBLGen Pro, the productive O/R mapper for .NET LLBLGen Pro website: http://www.llblgen.com My .NET blog: http://weblogs.asp.net/fbouma Microsoft MVP (C#) ------------------------------------------------------------------------
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|