Dynamically adding select fields using LINQ lambda - c#

Lets say we have an expression:
var prices = from p in PriceDB.Prices
where p.TypeID == 12
orderby p.PriceType.Title
select p;
Is it possible to modify the select list?
I imagine it looking something like this:
var newPriceList = prices.Select( p => p.ExchangeRate );
This may be an odd request, but in my code (which is too long and complex to post here) I want to conditionally add fields to be output depending on a CheckBoxList.
I assume, of course, that I'm trying to go about this the wrong way...

I imagine it looking something like this:
Actually it would look exactly like that. First, build a query, selecting the entire record. Then add a select (using the Select() method seem the easiest way) to limit the selection. Linq-to-Sql will sort out the two selects, and use the proper reselt, so theres just one select in the final SQL.
There's no really good way to choose between multiple selects. I would probably use a switch/case.

While you could go down the dynamic route, I would strongly consider not doing so. What is the cost of fetching the extra values if you don't need them, in your particular case? Is the problem that they're being displayed dynamically and you only want them displayed in certain cases? If so, I'd suggest modifying the display code somehow.
It's hard to stay strongly typed (which has various advantages) while being dynamic in terms of what you fetch. Of course, if you always want to fetch the same "shape" of data (e.g. always just a decimal value from each row) then that's reasonably easy - let me know if that's something you'd like to see demonstrated.
If you could tell us more about your problem, we may be able to suggest alternative solutions.

If I understood you correct this is explaining how to build dynamic queries:
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

You might want to look at this Dynamic LINQ and Dynamic Lambda expressions?
Or the Dynamic Expression API (System.Linq.Dynamic).

Related

sorting, filtering, and paging with entity framework core 2

I'm creating a tabular grid of data and will have every column header sortable (both ascending and descending) as well as filterable by a textbox underneath the column name.
I've done some digging to find out the best approach to generating my LINQ queries for entity framework and best I found was this: https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/sort-filter-page?view=aspnetcore-3.0
That just uses a big switch / case (for ordering only...doesn't even consider multiple filtering options beyond one). Surely there's got to be a better, more concise approach than this?
I'm half tempted to just use my old sproc and call the sproc with EF if this is really the path I'll have to go down.
Ideally, I'd want something like this:
return myContext.Where(x =>
x.%thisisadynamicfield%.Contains("%somefiltervalue%" &&
x.%anotherdynamicfield%.Contains("%someothervalue%" && ...)
.OrderBy(x => x.%someorderybydynamicfield%)
I'm ok using a conditional to determine ordering ascending or descending, but I'd really like to compact everything else as much as possible and that MS article I linked above looks like code vomit and it would only cover part of my needs.
EDIT: as is almost always the case, as soon as I post here and try one more searching effort, I find what I'm looking for. I just found this: https://github.com/harshwPro/EntityFrameworkPaginate which looks very promising. I will report back here if that solves my issue.
EDIT 2: well the github project I referenced in my first edit is certainly a cleaner solution than the MS article I posted originally but it still leaves me with writing a huge conditional to generate my filters by property. Using that solution, I'd have to write something like this:
dataPagingModel.Filters.Add(true, x => x.MyCoolProperty.Contains("blah")); but would have to conditionally add new filters based on my angular presentation layer's posted parameters - switch / case, or some huge if / else block. What I'd ideally like is a way to just loop over all of the posted filters list and dynamically add those filters in a loop. So I guess my question now boils down to, is there a way to access properties of an object dynamically (generically) in a lambda expression?
EDIT 3: I think this SO post has the answers I need: Generic method to filter a list object

Linq select where has at least one entry in another table

I have the following structure that I wan't to query using Linq, specifically Linq to Entities (Enitity Framework).
Table1: RouteMeta
Table2: SitePage
Multiple SitePages can link to the same RouteMeta.
I'm querying the Route Meta to select a number of rows. I'm using a generic repository, currently like this:
return r.Find().ToList();
There's nothing special about it - the Find method accepts an optional linq expression, so I could do something like this:
return r.Find(x => x.Status=1).ToList();
However, what I actually want to do is to select rows from RouteMeta where at least one linked row exists in SitePages with a property IsPublished = true.
return r.Find(x => x.SitePages("where y => y.IsPublished = true");
Obviously, the above isn't correct, I'm just trying to explain the scenario better.
Any advice appreciated.
try something like
return r.Find(x=>x.Sitepages.Any(y=>y.Published))?
I'd also suggesting using a profiler if possible to check that this translates properly into SQL. It probably should do but it depends on how your repository works.

Dynamic select fluent nhibernate

First of all, sorry for my bad english.
I have a little trobule figurering this one out.
I have three tables and I need to make it so that the user can decide witch columns to fetch from the database.
I have tried using Dynamic nuget, but wont work.
The code i need is something like the line below.
var res = session.QueryOver<MyObject>().Select(x => x.decidedByUser).List();
Is this even possible or do I need to make some kind of workaround? Maybe something like getting all the values and then select? :-)
var columnProjection = Projections.Property(() => aliasForTable.Column1)
you can use above variable in nhibernate select statement to decide which column you want to fetch. Create this assignment for each of your case and you're done

How to build a LINQ query from text at runtime?

I have a
class A {
public int X;
public double Y;
public string Z;
// and more fields/properties ...
};
and a List<A> data and can build a linq query like e.g.
var q = from a in data where a.X > 20 select new {a.Y, a.Z};
Then dataGridView1.DataSource = q.ToList(); displays the selection in my DataGridView.
Now the question, is it possible to build the query from a text the user has entered at runtime? Like
var q = QueryFromText("from a in data where a.X > 20 select new {a.Y, a.Z}");
The point being, that the user (having programming skills) can dynamically and freely select the displayed data.
Dynamic Linq baby!
r.e. comment.
Yes, the example as written may not be possible using Dynamic Linq, but if you factor out the constants, e.g. 'from a in data' you are left with a 'where' and a 'select' which can be expressed with dynamic linq.
so two text boxes, maybe three if you include an orderby, could possibly satisfy your requirements.
Just a thought.
Jon has an interesting approach but i would be leery of compiling and executing unrestrained code.
Well, you can use CSharpCodeProvider to compile code at execution time. Have a look at Snippy for an example of this. In this case you'd need to compile the user code in a method which accepts a List<A> called data. My experience is that it works, but it can be slightly fiddly to get right - particularly in terms of adding the appropriate references etc.
Answering it pretty late; though, it will help someone who visits this page.
I had similar requirement and I solved it by dynamically compiling string as LINQ query, executing it over in-memory collection and collecting the result. Only catch is user input needs to be valid C# compile-able code else it returns an exception message instead of result.
Code is pretty long so here is the github link
Sample application on github shows multiple examples including projection.
Although there may be some ways to do this, LINQ simply isn't designed for this scenario. Using CodeDOM (as Jon suggested) is probably the only way to get that easily done. If you trust the user and he/she has programming skills, you could perhaps just use old fashioned methods and let the user enter the query using SQL?
If you, on the other hand, choose to create some visual tool for constructing queries, you don't need to build them by composing strings and you can compose expression trees instead. For example using Linq Kit and AsExpandable.
check out this library
http://msdn.microsoft.com/en-us/vcsharp/bb894665.aspx

Linq2Entities, many to many and dynamic where clause

I'm fairly new to Linq and struggling using dynamic where over a many to many relationship.
Database tables are like so:
Products <-> Products_SubCategories <-> SubCategories
with Products_SubCategories being a link table.
My full linq statement is
db.Products.Where("it.SubCategories.SubCategoryID = 2")
.Include("SubCategories")
.OrderBy(searchOrderBy)
.Skip(currentPage * pageSize)
.Take(pageSize)
.ToList()
.ForEach(p => AddResultItem(items, p));
So ignoring everything bar the Where() I'm just trying to pull out all products which are linked to sub category ID 2, this fails with
To extract properties out of collections, you must use a sub-query to iterate over the collection., near multipart identifier, line 8, column 1.
I think using the SQL-esque syntax I can do a subquery as per this link. However I'm not sure how to do that in the lambda / chaining syntax.
This is the start of a search function and I would like to build up the where string dynamically, as I have with the searchOrderBy string to avoid a large SELECT CASE. Products is linked to another table via a link table that I will need to include once I understand how to do this example.
Any help would be much appreciated!
Thanks
This is wrong:
db.Products.Where("it.SubCategories.SubCategoryID = 2")
SubCategories is a list. It does not have a property called SubCategoryID. Rather, it contains a group of entities which each have a property called SubCategoryID. That's a critical distinction.
When you run into a situation where you don't know how to proceed in there are multiple problems, it is good to break the problem down into several, smaller problems.
Let's start by removing the dynamic query. It will be easier to solve the problem with a non-dynamic query. Once you've done that, you can go back and make it dynamic again.
So start by using the non-dynamic syntax. Type something like this in Visual Studio, and see what IntelliSense does for you:
db.Products.Where(p => p.SubCategories.
You will quickly see that there is no SubCategoryID property. Instead, you will see a bunch of LINQ API methods for working with lists. If you know LINQ well, you will recognize that the Any() method is what you want here:
db.Products.Where(p => p.SubCategories.Any(sc => sc.SubCategoryID == 2))
Go ahead and run that query. Does it work? If so, you can move ahead to making it dynamic. I'm no ESQL expert, but I'd start with something along the lines of:
db.Products.Where("EXISTS(SELECT SC FROM it.SubCategories AS SC WHERE SC.SubCategoryID = 2");
As an aside, I use MS Dynamic Query ("Dynamic LINQ") for this sort of thing rather than Query Builder, as it's more testable.
It worked for me.
db.Products.Where("SubCategories.Any(SubCategoryID = 2)")

Categories