10

So I've been developing with Entity + LINQ for a bit now and I'm really starting to wonder about best practices. I'm used to the model of "if I need to get data, reference a stored procedure". Stored procedures can be changed on the fly if needed and don't require code recompiling. I'm finding that my queries in my code are looking like this:

List<int> intList = (from query in context.DBTable
                     where query.ForeignKeyId == fkIdToSearchFor
                     select query.ID).ToList();

and I'm starting to wonder what the difference is between that and this:

List<int> intList = SomeMgrThatDoesSQLExecute.GetResults(
                                  string.Format("SELECT [ID]
                                                 FROM DBTable
                                                 WHERE ForeignKeyId = {0}",
                                  fkIdToSearchFor));

My concern is that that I'm essentially hard coding the query into the code. Am I missing something? Is that the point of Entity? If I need to do any real query work should I put it in a sproc?

James Wiseman
  • 29,946
  • 17
  • 95
  • 158
jermny
  • 870
  • 2
  • 12
  • 23
  • The second query is not a `stored procedure`. The stored procedure will be written inside your database and the Entity code will just call it.Instead of writing `select` statement write the name of stored procedure – Amir Ismail Jan 16 '12 at 12:12
  • I'm aware that it isn't a stored procedure. I'm trying to point out that if I do a LINQ query against an entity context, it looks the exact same as if I just hard coded the SQL query into the code. – jermny Jan 16 '12 at 12:13
  • 2
    Always wondered about this. Would be interested to see the answer! – James Wiseman Jan 16 '12 at 12:16
  • Coming from a db oriented background, where I've always used ADO.NET directly for performance without any LinqToSql/EF middle-men, I have similar concerns along these lines too – AdaTheDev Jan 16 '12 at 12:22
  • 4
    Also, second query example is prone to SQL injection. – vgru Jan 16 '12 at 12:25

5 Answers5

11

The power of Linq doesn't really make itself apparent until you need more complex queries.

In your example, think about what you would need to do if you wanted to apply a filter of some form to your query. Using the string built SQL you would have to append values into a string builder, protected against SQL injection (or go through the additional effort of preparing the statement with parameters).

Let's say you wanted to add a statement to your linq query;

IQueryable<Table> results = from query in context.Table
                            where query.ForeignKeyId = fldToSearchFor
                            select query;

You can take that and make it;

results.Where( r => r.Value > 5);

The resulting sql would look like;

SELECT * FROM Table WHERE ForeignKeyId = fldToSearchFor AND Value > 5

Until you enumerate the result set, any extra conditions you want to decorate will get added in for you, resulting in a much more flexible and powerful way to make dynamic queries. I use a method like this to provide filters on a list.

tbddeveloper
  • 2,407
  • 1
  • 23
  • 39
  • You make a good point but it makes me wonder if ease of use is more important that having versatile queries. Is it more important to have the convenience of LINQ queries at a cost of having them hard coded in your application, forcing updates when those queries change even slightly? – jermny Jan 16 '12 at 12:22
  • 1
    I created repositories that always return SELECT * FROM Table. I apply a layer of "access rights" from my application in-between that and the normal development, because I want to take the burden off development. Using this method, I still provide the developer with the ability to manipulate the query further, adding their own filters. – tbddeveloper Jan 16 '12 at 12:25
10

I personally avoid to hard-code SQL requests (as your second example). Writing LINQ instead of actual SQL allows:

  • ease of use (Intellisense, type check...)
  • power of LINQ language (which is most of the time more simple than SQL when there is some complexity, multiple joins...etc.)
  • power of anonymous types
  • seeing errors right now at compile-time, not during runtime two months later...
  • better refactoring if your want to rename a table/column/... (you won't forget to rename anything with LINQ becaues of compile-time checks)
  • loose coupling between your requests and your database (what if you move from Oracle to SQL Server? With LINQ you won't change your code, with hardcoded requests you'll have to review all of your requests)
  • LINQ vs stored procedures: you put the logic in your code, not in your database. See discussion here.

if I need to get data, reference a stored procedure. Stored procedures can be changed on the fly if needed and don't require code recompiling

-> if you need to update your model, you'll probably also have to update your code to take the update of the DB into account. So I don't think it'll help you avoid a recompilation most of the time.

Community
  • 1
  • 1
ken2k
  • 48,145
  • 10
  • 116
  • 176
5

Yes, if you're good at SQL, you can get all that with stored procs, and benefit from better performance and some maintainance benefits.

On the other hand, LINQ is type-safe, slightly easier to use (as developers are accustomed to it from non-db scenarios), and can be used with different providers (it can translate to provider-specific code). Anything that implements IQueriable can be used the same way with LINQ.

Additionally, you can pass partially constructed queries around, and they will be lazy evaluated only when needed.

So, yes, you are hard coding them, but, essentially, it's your program's logic, and it's hard coded like any other part of your source code.

vgru
  • 49,838
  • 16
  • 120
  • 201
5

Is LINQ is hard-coding all your queries into your application? Yes, absolutely.

Let's consider what this means to your application.

If you want to make a change to how you obtain some data, you must make a change to your compiled code; you can't make a "hotfix" to your database.

But, if you're changing a query because of a change in your data model, you're probably going to have to change your domain model to accommodate the change.

Let's assume your model hasn't changed and your query is changing because you need to supply more information to the query to get the right result. This kind of change most certainly requires that you change your application to allow the use of the new parameter to add additional filtering to the query.

Again, let's assume you're happy to use a default value for the new parameter and the application doesn't need to specify it. The query might include an field as part of the result. You don't have to consume this additional field though, and you can ignore the additional information being sent over the wire. It has introduced a bit of a maintenance problem here, in that your SQL is out-of-step with your application's interpretation of it.

In this very specific scenario where you either aren't making an outward change to the query, or your application ignores the changes, you gain the ability to deploy your SQL-only change without having to touch the application or bring it down for any amount of time (or if you're into desktops, deploy a new version).


Realistically, when it comes to making changes to a system, the majority of your time is going to be spent designing and testing your queries, not deploying them (and if it isn't, then you're in a scary place). The benefit of having your query in LINQ is how much easier it is to write and test them in isolation of other factors, as unit tests or part of other processes.

The only real reason to use Stored Procedures over LINQ is if you want to share your database between several systems using a consistent API at the SQL-layer. It's a pretty horrid situation, and I would prefer to develop a service-layer over the top of the SQL database to get away from this design.

Paul Turner
  • 38,949
  • 15
  • 102
  • 166
  • I agree with your sentements. However, there is something to be said for having a self consistant database that could be accessed directly without any danger of true inconsistancy. (i.e. constraints or triggers enforcing all consistancy rules that are fundemental to the data.) This is becasue the database may well outlive the original service-layer that used it. I don't recommend accessing the database directly if a service layer exixts, but ideally doing so should not be dangerous. – Kevin Cathcart Jan 16 '12 at 16:21
  • 1
    I wouldn't argue that constraints (and to a lesser-extent, triggers) are tools you should throw away. They're an essential part of data-integrity, and data-integrity is the core responsibility of the database. – Paul Turner Jan 16 '12 at 16:31
  • Good. Many people who use ORMs like to simply maintain integrity in the code. When not using a shared service layer that is distasterous, but when you do use one, you can often get away with it. If I am understanding you correctly: You agree then that the databsse is reponsible for storage and integretry and if one desires a common API to the database for multiple applications, a service layer is preferable to thousands of stored procedures. That makes good sense to me. – Kevin Cathcart Jan 16 '12 at 16:43
3

I also wondered about that, but the mentality that database interactivity is only in the database tier is an outmoded concept. Having a dedicated dba churn out stored procedures while multiple front end developers wait, is truly an inefficient use of development dollars.

Java shops hold to this paradigm because they do not have a tool such as linq and hold to that paradigm due to necessity. Databases with .Net find that the need for a database person is lessoned if not fully removed because once the structure is in place the data can be manipulated more efficiently (as shown by all the other responders to this post) in the data layer using linq than by raw SQL.

If one has a chance to use code first and create a database model from the ground up by originating the entity classes first in the code and then running EF to do the magic of actually creating the database...one understands how the database is truly a tool which stores data and the need for stored procedures and a dedicated dba is not needed.

ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
  • 3
    In my experience, the database in any sizeable system is usually the performance bottleneck and so it's critical to ensure queries are performant and tuned appropriately. Which means, someone who is database-oriented is crucial if you want to scale. My concern is always, that if the db is treated as a 2nd class citizen, then sooner or later it will bite you when it performs badly. – AdaTheDev Jan 16 '12 at 14:12
  • 1
    @AdaTheDev (*I did some ada back in the 80s*). I heartily agree with you. Any technology can quickly go into the weeds. Just like machine code paradigm where one programs in an advanced language which creates the machine code, it won't be as fast as tweaked assembly code. But the trade off is there for time to complete verses speed; same holds when using linq. – ΩmegaMan Jan 16 '12 at 14:18
  • yes, I can't argue there - it certainly does improve productivity, so I can see benefits there. Though finding it does conflict with my inner database-geek! – AdaTheDev Jan 16 '12 at 14:23