This gets into some of the plumbing behind Linq2Entities and the difference between Linq2Objects and Linq2AnythingElse You obviously have a good understanding of expression trees and you're generating them programatically. Linq2Entities takes that expression tree and tries to convert it to a SQL query to run on the database server. However, It can't map arbitrary C# code onto its SQL equivalent (for example, the toBll call has absolutely no significance in SQL) In other words, you're hitting this problem because Linq2Entities is attempting to map your toBll call into SQL, and is failing miserably because there is no such equivalent.
There is a bit of a design flaw in what you're trying to do. I'm assuming that you're trying to get the arbitrary condition expressed in "where" to run on the database server. However, your arbitrary condition is in terms of your business layer objects, and neither SQL server nor the entity framework know anything about these objects What you really need to do for this sort of design, is to have the arbitrary condition expressed in terms of the Linq2Entities types, not your BLL types.
Since Linq2Entities knows about these types, it will be able to translate the arbitrary expression into SQL (since it has the mappings for the Linq2Entities types to their SQL equivalents) What I described above is really the proper way to do this, alternatively, you could enumerate the query (which will execute) and then run the conditions against the returned result set. Since at this point you're running in Linq2Objects (which is just standard . NET code running against in-memory objects), your functions will run without issues.
However, this means that your "where" clause will be run in-memory, and NOT on the database server, so I would really not recommend this EDIT: OP requested code In order for this to work properly, you need to change your GetSingle method to take an expression condition that acts on the EntityFramework type, and not on your BLL type. You can then remove your converter clause from the expression tree, and you should be up and running: public CategoryViewModel GetSingle( Expression> where) { var param = Expression. Parameter(typeof(DAL.EntityModels.
Category), "category"); var body = Expression. Invoke(where, param); var lambda = Expression. Lambda>(body, param); return ToBLL((DAL.EntityModels.
Category)_categoryRepository. GetSingle(lambda)); } The problem with this approach is that your expression must be in terms of your EntityFramework type, which might violate your desire to hide the details of the data abstract layer. At that point, its pretty much tough luck, EntityFramework + BLL + Dynamic Query Generation = hard to get right.
This gets into some of the plumbing behind Linq2Entities and the difference between Linq2Objects and Linq2AnythingElse... You obviously have a good understanding of expression trees and you're generating them programatically. Linq2Entities takes that expression tree and tries to convert it to a SQL query to run on the database server. However, It can't map arbitrary C# code onto its SQL equivalent (for example, the toBll call has absolutely no significance in SQL).
In other words, you're hitting this problem because Linq2Entities is attempting to map your toBll call into SQL, and is failing miserably because there is no such equivalent. There is a bit of a design flaw in what you're trying to do. I'm assuming that you're trying to get the arbitrary condition expressed in "where" to run on the database server.
However, your arbitrary condition is in terms of your business layer objects, and neither SQL server nor the entity framework know anything about these objects. What you really need to do for this sort of design, is to have the arbitrary condition expressed in terms of the Linq2Entities types, not your BLL types. Since Linq2Entities knows about these types, it will be able to translate the arbitrary expression into SQL (since it has the mappings for the Linq2Entities types to their SQL equivalents).
What I described above is really the proper way to do this, alternatively, you could enumerate the query (which will execute) and then run the conditions against the returned result set. Since at this point you're running in Linq2Objects (which is just standard . NET code running against in-memory objects), your functions will run without issues.
However, this means that your "where" clause will be run in-memory, and NOT on the database server, so I would really not recommend this EDIT: OP requested code... In order for this to work properly, you need to change your GetSingle method to take an expression condition that acts on the EntityFramework type, and not on your BLL type. You can then remove your converter clause from the expression tree, and you should be up and running: public CategoryViewModel GetSingle( Expression> where) { var param = Expression. Parameter(typeof(DAL.EntityModels.
Category), "category"); var body = Expression. Invoke(where, param); var lambda = Expression. Lambda>(body, param); return ToBLL((DAL.EntityModels.
Category)_categoryRepository. GetSingle(lambda)); } The problem with this approach is that your expression must be in terms of your EntityFramework type, which might violate your desire to hide the details of the data abstract layer. At that point, its pretty much tough luck, EntityFramework + BLL + Dynamic Query Generation = hard to get right.
What you really need to do for this sort of design, is to have the arbitrary condition expressed in terms of the Linq2Entities types, not your BLL types...... --- please, provide me an example of code. – Alex Maslakov Feb 28 at 21:31 Updated with code, probably not exactly what you're hoping for, but perhaps it will show you exactly why what you have doesn't work – LorenVS Feb 28 at 21:37 It doesn't work too - "Expression of type 'DAL.EntityModels. Category' cannot be used for parameter of type 'BLL.
CategoryViewModel'" - on line "var body = Expression. Invoke(where, param);" – Alex Maslakov Mar 1 at 5:53 Expression> where - hmmm.... I've not sighted – Alex Maslakov Mar 1 at 6:44.
This problem can be solved using the AsExpandable() method present in LINQKIT by Joe Albahari. He's the same creator of PredicateBuilder that I see you're using. You can grab LINQKIT DLL here or install it through a NuGet package here.
It'll certainly solve your problem because it has solved mine.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.