Linq Select Column by string Column name without reflection or library - c#

I am trying
_context.Entity
.Include(x => x.Addresses)
.Select(/*I want to pass string column name to get it instead of (x => x.Column)*/);
any recommendations?
I have tried the Dynamic.Linq library and reflection but I am trying to find something with better performance..

Related

How to group records in Entity Frameworkk with where clause

i want to apply where clause on COLID column and wish to take the very last value w.r.t that COLID, e.g in COLID 1 case the last returned value should not be NULL and in COLID 2 it would be 30, against each ENTRYID
I can do it well in SQL, look at the query and data:
You can edit your question to append code rather than pasting it into comments. Paste the code into the question and use the "{}" button in the editor to code format.
You can group and sort items in Linq without too much issue.
context.Entries
.GroupBy(x => x.EntryID)
.Select(x => x.OrderByDescending(y => y.ColID).FirstOrDefault())
.ToList();
GroupBy defines what columns make up the unique grouping. In your case if you want the latest Entry then the EntryId would be enough to define what to group on. This will form the Key for each group. From there we use Select to tell it what to select from each group. The group will be all entries of that EntryID so we order by the ColID descending so the biggest one is first, then use FirstOrDefault to take the largest one. The ToList() at the end materializes the result to retrieve the latest ColID version of each EntryID.
Edit: If you want to only consider non-null values:
context.Entries
.Where(x => x.ColValueId != null)
.GroupBy(x => x.EntryID)
.Select(x => x.OrderByDescending(y => y.ColID).FirstOrDefault())
.ToList();
Linq is a bit different than SQL and can have some limitations when used with EF because EF will ultimately need to convert it to SQL. Still, it is well worth reading up on Linq because it is a very powerful tool when working with objects and it allows EF to do a lot of the heavy lifting.

Linq filters required on Project Context object

I am trying to get a filtered list from MS Project and filter on the name by using something akin to contains so that we can return a reduced set of results to process.
projContext.Load(projContext.Projects, qp => qp.Include(qr => qr.Id, qr => qr.Name));
I seem to have exhausted all the options that I know about and trying to use contains isn't working for me.
Intellisense allows this . . . (but doesn't like it at run time)
projContext.Load(projContext.Projects, qp => qp.Include(qr => qr.Id, qr => qr.Name.Contains("myfilter")));
I dont know if i am understanding what is your difficulty but, to obtain the list of projects filtered by " name contains the 'myfilter'. Try this
using (var context = new projContext())
{
var projects = context.Projects.Where(p => p.Name.Contains("myfilter")).ToList();
}
https://learn.microsoft.com/en-us/ef/core/querying/related-data
.Include() is an EF Query extension that includes the navigation property you requesting, since Id and Name ( can't know for certain since you didn't provided your model class ) most certainly are values stored in the database you don't have to Include them on your query. If you are looking to filter by contains to minimize the result of your query simply add a to your query your filters like so :
projContext.Projects.Where(project => project .Name.Contains("myfilter")));

Search and select multiples with where linq/lambda expressions

I currently have the following code:
var FirstNameList = db.Clients.Include(x => x.FirstNames).Include(x => x.Addresses).SelectMany(a => a.FirstNames).Where(x => x.Name.ToLower().Trim() == "Max".ToLower().Trim()).ToList();
I have a navigation property of FirstNames and Addresses which I which to include in the result.
I use the SelectMany Statement because it, for me, is the only one which works. Kind of. It returns all the FirstNames where the Name equals Max.
What I would like it to do is return all the Clients who have the property Name equals Max from the table FirstNames.
the other way I thought about doing this was to take all the ID's returned from FirstNameList and then returning the Clients by querying the data against the FirstNameList but I would be then querying the database twice, which seems inefficient.
My question is is it possible, and how would I go about querying the database to return my Clients, if it was?
Kind regards
The following query should give you what you're looking for. You can look within each client's FirstNames and see if any of them are named "max". (In this case, since "max" is a constant you're typing in, I removed the ToLower().Trim() from it)
var clientsNamedMax = db.Clients.Include(x => x.FirstNames).Include(x => x.Addresses).Where(x => x.FirstNames.Any(y => y.Name.ToLower().Trim() == "max")).ToList();

Unable to cast left join

I am trying to add a feature to my search page. Basically, if a certain condition is true (based on joining with another table), then apply some CSS class. Here are my (simplified) models:
MyTable
int Key
string Someinfo1
string Someinfo2
string CssClass
SomeTable
int Key
string CssClass
Using LINQ, I wish to join the two tables and assign SearchResult.CssClass = SomeTable.CssClass. In reality, there is some logic used for this assignment.
var test = db.MyTable
.GroupJoin(db.SomeTable,
m => m.Key,
s => s.Key,
(m, s) => new {m, s})
.SelectMany(x => x.h.DefaultIfEmpty(),
(x, y) => new MyTable
{
Key = x.m.Key,
Someinfo1 = x.m.Someinfo1,
Someinfo2 = x.m.Someinfo2,
CssClass = y.CssClass
}
This code breaks, giving the error
The entity or complex type 'MyTable' cannot be constructed in a LINQ to Entities query.
If I simply change the casting (x, y) => new MyTable to create an anonymous type (x, y) => new then things work how I expect them to. Though, I need this to have a typed as MyTable to be compatible with the view that currently exists. Why does it break when trying to cast, when it works fine otherwise? Casting after the fact doesn't work either. Thanks in advance
EDIT: To clarify, MyTable maps to a database table with the exception of CssClass. I have configured EF to ignore that element
modelBuilder.Entity<MyTable>().Ignore(m => m.CssClass);
The desired value for MyTable.CssClass comes from SomeTable.
DefaultIfEmpty() is used to include all entries in MyTable. There exist cases where a Key exists in MyTable, but not SomeTable
Just like the error says, you cannot create a new instance of an entity from within a query.
It appears you're trying to override a property of MyTable with a property from SomeTable. One drawback to that solution is that the new CssClass value will be saved back to MyTable if the entity is saved (which ma be what you want, but it doesn't seem like it based on your usage). If you really need to do this, you're going to have to hydrate the entities (e.g. with ToList()) and then loop to update the value with the value from the related entity.
Your best bet is probably going to be to create a type that is independent of your actual entity class that your views use rather than coupling the views to your entity class. It adds some work to map between the two classes but you can avoid problems like the one you're facing. One challenge I can already see with your data model - how do you know if the CssClass value should be saved back to MyTable or SomeTable?

LINQ: Multiple LIKE clauses in a single predicate

I'd like to do a LINQ query that can compare multiple variables to a single string. I've seen LINQ for LIKE queries of array elements, and it's helpful, but not quite. I need the reverse.
What I'd like to do is the following: let's say I have a Company object with both Name and Address. I also have a string keyword. Then, I'd like to find all Companys in a list that have the keyword in either their Name or Address. In SQL it would be...
SELECT * FROM Company
WHERE Name LIKE '%keyword%' OR Address LIKE '%keyword%'
I've been using Entity Framework, and I've tried the following: context.Companies.Where(x => new string[] { x.Name, x.Address }.Contains(keyword), as well as context.Companies.Where(x => new string[] { x.Name, x.Address }.Any(r => r.Contains(keyword)), but neither were successful. The first one gives me an IN clause, and the second one... I don't know what it does, but it doesn't give me what I want.
I'm sorry I don't have a very in-depth understanding of Expressions (yet); I wished I was able to write my own custom Expressions from scratch, but scratch it I can't just yet... Can anybody help me with this?
Any reason for not just using the || operator?
context.Companies.Where(x => x.Name.Contains(keyword) ||
x.Address.Contains(keyword))
I'd expect this to be translated into your original SQL.

Categories