Can I use array in the LINQ where expression? - c#

Would it be possible to use something like .Where(u => u.License_ID == ID) with ID being an array?

The code
Where(u => IDs.Contains(u.License_ID))
could work, but it depends on your database provider whether it supports that. If this is not a database query, but LINQ to objects, it will certainly work.

If the array contains custom objects, you could always write an extension method like
Equals(this Array[] _Array)
And define in there what are the requirements for equality.
Then your code becomes:
.Where(u => u.License_ID.Equals(ID))
And it would be highly reusable =)

Related

IN Operator between 2 collection objects

In Sql, I know we have the IN operator and the equivalent of that is .Contains() in LINQ but i am stuck on one problem here
Consider the following linq query:
_dbContext.Offices.Where(o => o.Id == policy.OfficeId).FirstOrDefaultAsync()
Suppose i were to introduce a policies (plural) object which is a collection object each policy in the collection has its own officeId, how do I check if the offices collection consists of the officesId from policies collection object? I would like to do this in method syntax if possible. Thanks in advance.
Without having access to your data model, your answer does seem plausible; however, you need to have a call to .ToListAsync() at the end for this to compile. Also, it's more efficient to use Any() (rather than .Select.Contains):
await _dbContext.Offices.Where(o => policies.Any(p => p.OfficeId == o.Id)).ToListAsync();
I'm not sitting in front of a compiler, but if you just want the first one, the following is even better IIRC:
await _dbContext.Offices.FirstOrDefaultAsync(o => policies.Any(p => p.OfficeId == o.Id));
I think the following might work:
await _dbContext.Offices.Where(o => policies.Select(p => p.OfficeId).Contains(o.Id))

Clearing up many-to-many in Entity Framework 6 and Entity Framework Core querying

I have to eat humble pie and admit that I thought I understood many to many in EF6 and EFCore. I have your standard example, many students many subjects scenario, but the problem comes when I try to navigate the collections to get at specific properties during projections that I get stuck and can't figure out how to use either Select or SelectMany to get at properties in my projection.
So for example how would I use either Select or SelectMany to finish this?
I need to understand properly these two LINQ methods but can anyone help me?
Here is an example of where I'm stuck:
return await _db.Subjects
.Include(s => s.Teachers)
.Include(s => s.Students)
.Where(s => s.Students.Select(x => x.Class.ClassName).Contains(classname))
.Select(s => new SubjectViewModel
{
Class = s.Students.Select(p => p.Class.ClassName)
})
So how do I complete this, do I do a SelectMany or Select? Oh and can anyone point me to some content other than MSDN to properly understand Select and SelectMany? Also can anyone show me how this would be done in EFCore? I think I just need help.
Based on what we have to work with (as #Matthew Cawley said in the comment) if you use Select you get an object of type IEnuberable<IEnumerable<string>> or IQueryable<IQueryable<string>> which is a list of lists of strings.
If you need only one list of strings you can use SelectMany to iterate just like Select but flatten the results into one collection and then applies the selector you passed p => p.Class.ClassName.
If you want to concatenate them into a single string you can use string.Join(",", <collection>) but not directly in the projection if you are using linq-to-sql because it wouldn't know how to translate that into sql code.

When using LINQ to Entities, is there a better method than casting to list in order to use unsupported code/extensions?

I find myself needing to do things like this frequently, and I'm just curious if there is a better way.
Suppose I have a class that holds a snapshot of some data:
private List<Person> _people;
In some method I populate that list from a LINQ query using Entity Framework, and perhaps I need to, for example, run a custom IEqualityComparer on it. Since this isn't supported in LINQ to entities, I end up with something like this:
_people = db.People.Where(...)
.ToList()
.Distinct(new MyCustomComparer())
.ToList();
Another example might be using an extension method, which also is not supported in LINQ to entities:
_people = db.People.Where(...)
.ToList()
.Select(_ => new { Age = _.DOB.MyExtensionMethod() })
.ToList();
In order to use either of these I have to cast the database entities into regular memory objects with the first ToList(), and then since I ultimately want a list anyway, I have a final cast ToList() at the end. This seems inefficient to me, and I'm wondering if there's a better pattern for these types of situations?
You can use AsEnumerable():
_people = db.People.Where(...)
.AsEnumerable()
.Distinct(new MyCustomComparer())
.ToList();
Which is equivalent to:
IEnumerable<Person> _people = db.People.Where(...);
_people = _people.Distinct(new MyCustomComparer()).ToList();
This is not much of an improvement, but at least it doesn't create another List<T> and is better expressing that you want to switch to the realm of IEnumerable<T> (in-memory).
See MSDN

Custom Comparer in LINQ query to sort strings/numerics

I've written a custom comparer that sorts strings and numeric. This all works fine.
However I'm rewriting my whole BLL to use LINQ where possible as I do like the syntax. Now i'm stumbling onto using my custom comparer. As LINQ syntax (query based) will not allow to use custom comparers Im now using method based LINQ.
But in order to make it to work, I need to do an intermediate ToList(), which again works fine, but looks somewhat weird to me?
var areas = cc.Areas.Where(a => a.ProjectId == ProjectId).ToList()
.OrderBy(a => a.UnitNumber, new Common.Comparers.StringNumericComparer());
Now i'm unsure if this has to do with the SQL query to be executed first and then the results sorted in my C# code side, but this is beyond my knowledge.
Does ToList() force the first part of the linq query to be executed on the database?
Yes your understanding is correct. Until the .ToList() it is an IQueryable. On ToList() a database query is fired and the results are fetched in memory and then a sort occurs on the List.
Your comparer cannot execute before this since it does not translate to an SQL query.
Yes, .ToList() forces your Areas to be loaded and the sorting occurs in memory.

Converting IQueryable<T> object to another object?

I have no idea what the keywords are so here is an example of what I want:
return from i in userRepo.GetUsers()
select new SimpleUser{
i.UserId,
i.Name
};
userRepo.GetUsers() returns type IQueryable<User>. I'd like to convert this to IQueryable<SimpleUser> to I can restrict access to certain properties of the User domain.
How do I do this without hard coding the translation like this? What about tools like automapper or ValueInjecter, how can they do this?
Also, what is this technique called?
You must hardcode the translation or you must first convert it to IEnumerable. IQueryable represents expression tree translated to some execution in used provider - in your case I believe it will be Entity framework. You can't use any automatic mapping in such query because it will be translated to SQL which will not understand your .net methods or AutoMapper. Projections to custom types are part of the query and must be hardcoded. You can create custom extension method to IQueryable and reuse it where you need:
public static IQueryable<SimpleUser> ProjectToSimpleUser(this IQueryable<User> query)
{
return query.Select(u => new SimpleUser
{
// Here map your fields
});
}
Now you can use:
return repo.GetUsers().ProjectToSimpleUser();
In case of Entity framework SimpleUser mustn't be an mapped entity.
Provided that SimpleUser is assigneable to User (User is an interface of baseclass of SimpleUser), you can
var users = simpleUsers.Cast<User>();
optionally with
var users = simpleUsers.Cast<User>().AsQueryable();
And if you're not sure whether all items are actually Users, then you can use OfType<User> instead of Cast<User>
AutoMapper is the tool you want; it works via reflection and unless you tell it to do otherwise, it will map properties with the same name directly.
Auto-mapping is the technique.
This question is 9 years old so idk if it existed then but for anyone searching now, using .FirstOrDefault() works if you pick a single user.

Categories

Resources