LINQ equal instead of Contains - c#

I need to use equal instead of Contains.
I have an array of codes called selectedDeviceTypeIDs i assume it has two codes {1,2}
I need get result from the query if Devices ids are exactly {1,2} so i have replace selectedDeviceTypeIDs.Contains with selectedDeviceTypeIDs.equal or something like that ...
m => m.Devices.Any(w => selectedDeviceTypeIDs.Contains(w.DeviceTypeID)
if (DeviceTypeIDs != null)
{
Guid[] selectedDeviceTypeIDs = DeviceTypeIDs.Split(',').Select(Guid.Parse).ToArray();
query = query.Where(j => j.HospitalDepartments.Any(jj => jj.Units.Any(m => m.Devices.Any(w => selectedDeviceTypeIDs.Contains(w.DeviceTypeID)))));
}

Use !.Except().Any() to make sure m.Devices doesn't contains any DeviceTypeID not present in selectedDeviceTypeIDs
query = query.Where(j => j.HospitalDepartments.Any(jj => jj.Units
.Where(m => !m.Devices.Select(w => w.DeviceTypeID).Except(selectedDeviceTypeIDs).Any())));

Option 1:
If you care about the Order of the items, use SequenceEqual extension method. This will return false, even if the collection has the items but in different order
m => m.Devices.Any(w => selectedDeviceTypeIDs.SequenceEqual(w.DeviceTypeID)
Option 2:
If you don't care about the order , use All extension method. This will return true, if the items in both collections are same irrespective of the order.
m => m.Devices.Any(w => selectedDeviceTypeIDs.All(w.DeviceTypeID.Contains)

You need to check if the selectedDeviceTypeIDs contains every device, and that every device contains selectedDeviceTypeIDs. You could use this:
query = query
.Where(j =>
j.HospitalDepartments.Any(jj =>
jj.Units.Any(m =>
m.Devices.All(
w => selectedDeviceTypeIDs.Contains(w.DeviceTypeID))
&&
selectedDeviceTypeIDs.All(
g => m.Devices.Select(d => d.DeviceTypeID).Contains(g))
)
)
);

Related

Cannot access groupBy data Linq C#

Inside method I have a list that contains grouped data:
var listofData = _context.DBONE.where(x => x.Id==3 && x.Status!=0)
.GroupBy(x => new { x.Name, x.Class })
.Select(q => new { Result = q.ToList() }).ToList();
if (methodParam == 10)
{
data = listofData.Where(x => FunctionCheck(---CANNOT ACCESS THE FIELDS FROM GROUP DATA TO PASS AS PARAMETERS---) == 10).ToList();
}
And this is the function that will receive 2 parameter from the grouped data:
private int FunctionCheck(int id, string name)
{...}
But, I cannot access the desired field inside 'listofData'. I can access only in case the listofData is not using groupBy().
If I understand what you are trying to do correctly, you are able to access your data but you are actually creating a "list of a list"
Watch my example, I think I have reproduced your scenario here:
As you can see, I then have a "result" which contains a list of users where Id == 3. The problem is that you create a new anonymous object with a props that is a list. So if you try the last thing you see in my image above, I think you will be able to access your rows.
The reason is that after your GroupBy call, the result is of a grouping type - every item of your list is an Enumerable of the original item, so you would have to operate on that grouping in a following manner:
// Groups such that all items in that group pass your check
listofData
.Where(group => group.All(item => FunctionCheck(item.Id, item.Name) == 10))
.ToList();
// Groups where at least one item matches
listofData
.Where(group => group.Any(item => FunctionCheck(item.Id, item.Name) == 10))
.ToList();
The desired outcome is not really clear from the question but this is the step you are likely missing.
Another approach which might be potentially useful is pre-filter the colleciton of items before grouping them:
var listOfGroupedDatas = _context.DBONE
.Where(x => x.Id ==3 && x.Status != 0 && FunctionCheck(item.Id, item.Name) == 10)
.GroupBy(x => new { x.Name, x.Class })
.ToList();
// This will result in a list of groupings in which all items pass your check
I think you want to call SelectMany to project into one dimensional array.
var listofData = _context.DBONE.where(x => x.Id==3 && x.Status!=0)
.GroupBy(x => new { x.Name, x.Class })
.SelectMany(q => q.ToList()).ToList();

Select all distinct last records of column1 and order by column2 in Linq (Not Working Accordingly)

So I have a table like this:
Now I want distinct ShortCode order by the ID descending. In other words, the distinct last records. Like this:
So I tried GroupBy like:
var data = db.ShortCodes.GroupBy(x => x.ShortCode).Select(x => x.FirstOrDefault()).OrderByDescending(s=> s.ID);
This gave me distinct records but not the last ones, nor ordered by ID descending:
Now I also tried like suggested here
var data = db.ShortCodeManager
.GroupBy(s => s. ShortCode)
.Select(g => g.First())
.OrderByDescending(s => s.ID);
This gave me the error The method 'First' can only be used as a final query operation. Consider using the method 'FirstOrDefault' in this instance instead.
So I modified to FirstOrDefault() like:
var data = db.ShortCodeManager
.GroupBy(s => s. ShortCode)
.Select(g => g.FirstOrDefault())
.OrderByDescending(s => s.ID);
This also gave me distinct records but not the last records:
So finally I tried like suggested here:
var data = db.ShortCodeManager.Where(a => a.ID > 0).GroupBy(x => x.ShortCode).OrderByDescending(grp => grp.Max(g => g.ID)).Select(a => a.FirstOrDefault());
Again, this gave me distinct records but not the last ones, nor ordered by ID descending:
So how am I to write the query to get the result I want in Linq? Also note, I need more of the distinct last records than ordering by ID descending. If anyone also knows how to write it in raw SQL it might be useful as well.
This LINQ query should work for your case:
var result = db.ShortCodeManager
.GroupBy(x => x.ShortCode)
.Select(gr => new { Id = gr.Max(g => g.Id), ShortCode = gr.Key})
.ToList();
EDIT:
Based on your comment it looks like you need to cast anonymous object result to ShortCodeManagerModel type and then pass it to your view. So, somethin like this:
var result = db.ShortCodeManager
.GroupBy(x => x.ShortCode)
.Select(gr => new { Id = gr.Max(g => g.Id), ShortCode = gr.Key})
.ToList();
var model = result
.Select(x => new ShortCodeManagerModel { Id = x.Id, ShortCode = x.ShortCode })
.ToList();
And then pass model to you view.

Dynamic linq query that Contains ALL from another list

I want to be able to find all orders with items that contain BOTH apples and oranges that I have in a list.
var itemToFind = new List<string>()
{
"apples",
"cookies"
};
How can I rewrite this so that Contains is dynamic?
This returns what I want but how do I make it loop through my list so that it is dynamic?
var query = result
.Where(o => o.OrderItems
.Any(i => i.Item.Name.Contains("apples")))
.Select(x => x)
.Where(y => y.OrderItems
.Any(b => b.Item.Name.Contains("cookies"))).ToList();
// returns 2 orders
Try something like this:
result.Where(o => o.OrderItems.Any(i => itemToFind.All(itf => i.Item.Name.Contains(itf)))).ToList()
This seems to work but not sure if that is the best way.
foreach (var item in listFacets)
{
// append where clause within loop
result = result
.Where(r => r.RecipeFacets
.Any(f => f.Facet.Slug.Contains(item)));
}

Create a C# dictionary from DB query with repeated keys

I have a Database with schools, and each school is in a City.
Now I want to create a dictionary that contains all the cities of each schoool. To achieve this I tried this approach:
var schoolCities = schoolsWithAddresses.Where(school => school.Address.City != null).ToDictionary(sc => sc.Address.City.Name.ToLower());
Now, the problem with this is that a City can have multiple schools. So, when I create my dictionary, I end up with an exception "Repeated Key".
I want to create a dicitonary because it will allow me to make a very quick lookup on the cities that have schools (that is why I am not using a List, for example).
How do I overcome this problem in a way rhat allows me to still make efficient lookups?
Use the ToLookUp extension method rather
var schoolCities = schoolsWithAddresses
.Where(school => school.Address.City != null)
.ToLookup(sc => sc.Address.City.Name.ToLower());
You should group the items first, so that you have unique cities.
schoolsWithAddresses.Where(school => school.Address.City != null)
.GroupBy(s => s.Address.City, (k, v) => new { City = k, Schools = v })
.ToDictionary(d => d.City, e => e.Schools)
;
Something like this:
Dictionary<string, List<School>> schoolCities = schoolsWithAddresses
.Where(school => school.Address.City != null)
.GroupBy(school => school.Address.City)
.ToDictionary(group => group.Key, group => group.ToList());
I think what you want is a Lookup:
Represents a collection of keys each mapped to one or more values.
Example usage:
Lookup<string, School> schoolCities = schoolsWithAddresses
.Where(school => school.Address.City != null)
.ToLookup(school => school.Address.City);
IEnumerable<School> schoolsInLondon = schoolCities["London"];
try this
var schoolCities = schoolsWithAddresses
.GroupBy(x => x.city!=null)
.ToDictionary(x => x.Key, x => x.ToList());

How to combine these two LINQ statements?

How can I combine these two LINQ statements into one?
var Priority = repository.GetMany<Letter>(l => l.UserID == currentUser.ID)
.Select(l => l.Priority)
.FirstOrDefault();
var User = repository.GetMany<Letter>(l => l.Priority > Priority)
.Select(l => l.User)
.FirstOrDefault();
I need to get Priority of the currentUser and then get the next user that has the next Priority. For example, if the Priority of currentUser is 1, I need to get the user with Priority == 2.
Example:
letter=new letter {
User=Mark, Priority=1
User=Raha, Priority=2
User=Searah, Priority=3
}
when currentUser is Mark with Priority=1,i need to get user with Priority=2,in this sample Raha!
Assuming that your GetMany are indeed just Where calls, and therefore they returns an IQueryable, the following should do the trick I think:
var users = repository
.GetMany<Letter>(l => l.Priority > (
repository.GetMany<Letter>(
l2 => l2.UserID = currentUser.ID
)
.Select(l2 => l2.Priority)
.First()
)
.OrderBy(l => l.Priority)
.Select(l => l.User)
.Take(1);
Your first query is basically just inserted in the second query.

Categories

Resources