6 ms·
One of the C# language features that makes LINQ so powerful is expression tree support; this allows the lambda (i.e. x => x * 2) to be read as a structured obje
by bigdubs 9y ago
One of the C# language features that makes LINQ so powerful is expression tree support; this allows the lambda (i.e. x => x * 2) to be read as a structured object and turned into something else (such as sql).
This would be pretty useful in ES7 or whatever spec is coming down the road for javascript.
- deleted 9y ago[deleted]
- bunderbunder 9y agoIn practice, it ends up being too powerful. The expression tree stuff tends to mostly be useful when you're using the IQueryable<T> interface. If there's a way to use IQueryable<T> to much effect without breaking encapsulation and creating tight coupling, I haven't seen it.
- jrs95 9y agoAt some point, you've got to have a layer that interacts with and is coupled to the database. Nothing is stopping you from creating abstractions above this. Why is this a problem?
- bunderbunder 9y agoIf you subscribe to the idea that the bit of your app that is coupled to the database should be very thin, then abstractions that live between that layer and the database tend to be a useless piece of excess complication. In the best case.
- Someone1234 9y agoI'm struggling to follow what you mean. Could you give an example?
- always_good 9y agoTake the simplest example where your code just calls `findUser(42)` and it runs `query('select * from users where id = $1', [42])`. Abstractions will add stuff on top of that which doesn't necessarily pay its own rent in benefits.
- bunderbunder 9y agoAssuming you've got a really thin data access layer, the general flow of things can be as simple as something like: call method -> execute SQL statement If you're sticking something that implements IQueryable<T> in there, then it becomes: call method -> execute LINQ query -> compile to SQL statement -> execute SQL statement I've found that those two extra steps in the middle typically add negative net value. They don't really make the code more readable; LINQ is so close to basic SQL that I can't fathom how a developer who can learn to write LINQ queries wouldn't be able to grok SQL. They cut you off from the full power of the database by limiting you to a sort of least common denominator version of the things you can do with real SQL (e.g., no PIVOT or MERGE if you're using mssql). They make the code harder to properly understand, because it's not readily apparent what will execute on the database. Some expressions will compile to SQL, some will execute in code, and some will execute in code and also force a bunch of other stuff that might have been compilable to SQL to execute in code instead. They will probably remove some boilerplate, but you can just as easily remove that boilerplate with a too like Dapper that doesn't come with all those other downsides.
- zip1234 9y agoA benefit is strong typing. A change in the model breaks the queries and the code doesn't compile. You change the database when you are using stored procedures or direct queries and your code still compiles fine.
- v-yadli 9y agoLINQ is not just for SQL. Say if your LINQ queries are but simply `where obj.prop == val`, you can have a Redis LINQ provider hot-swapped in. Even without the use of other backends it may still be beneficial. The "abstraction layer" need not to be thin as you explained here. You have the power to reinterpret and optimize your query. This allows visitor patterns (and maybe Roslyn-style analyzers) to kick in in the symbolic form, not just strings (indeed there's SQL parser, but again why? why limit it to SQL?)
- Someone1234 9y agoWhen you're directly interacting with the database tight coupling is always going to happen, and trying to hide that only adds needless complexity. The nice part about using Linq and IQueryable instead of e.g. query strings, is that the compiler (and intellisense) can check for some errors at compile-time instead of run-time. Just have to make sure your database model is 1:1 with the actual database. After you have the data you can throw it into a non-database DTO to re-couple a bit and pass it between layers.
- ianamartin 9y agoI disagree. You can and often should decouple from your database by calling only parameterized stored procedures. Your code only needs to know the name of the proc and the paeans to pass. In non-trivial applications this is where you get the best performance bang for your buck. ORMs are convenient dev tools, but I don’t see them as real options for deploying real apps of any meaningful scale.
- zip1234 9y agoPlenty of non-trivial applications use ORMs. StackOverflow uses an ORM (Dapper).
- kenoyer130 9y agoThere is a world of difference between a Micro-ORM such as Dapper and a bloated mess of an ORM like Entity Framework. They are not even close to the same thing.
- scarface74 9y agoStored Procedures -- oh $diety no. You can't unit test them, they are harder to rollback than code, more difficult to deploy.
- bunderbunder 9y agoYou can, and you should. http://tsqlt.org http://tsqlt.org Being able to write decent unit test suites is one of the biggest things that moved me from inline SQL back toward sprocs.
- scarface74 9y agoThere is no need for tight coupling or to expose an Iqueryable. You can write your repository with a method signature like this.... Find(<Expression<Func<Employee,bool>> query) {....} With Employee being a regular old undecorated POCO. Then if you call it: Find(e => e.id == 5) The repository can be searching for data in a SQL Server database using Entity Framework or a Mongo database using the Mongo driver or even an in memory list for unit testing and the calling code doesn't care. Yes the expression will be translated to the appropriate query (MongoQuery or SQL) without any coupling. You return a List<Employee> not an IQueryable.