Simple LINQ Order by not working - c#

I'm new with LINQ. I'm using this function:
public IEnumerable<Vendedores> GetVendedores()
{
using (var context = new OhmioEntities())
{
Vendedores _allvendors= new Vendedores();
_allvendors.Nombre = "All Vendors";
_allvendors.ID_Vendedor = -1;
var query = context.Vendedores;
var _vendors= query.Where(f => f.Activo == true).OrderBy(o=>Nombre).ToList();
_vendors.Insert(0, _allvendors);
return _vendors;
}
}
It should give me order list of active vendors. The where part work fine, but the order is ignored and the records after the .ToList are in the original table order. What i'm i doing wrong?
Thank you!

I think you need o.Nombre instead of Nombre
var _vendors = query
.Where(f => f.Activo)
.OrderBy(o=> o.Nombre)
.ToList();
Also f => f.Activo == true can be written as f => f.Activo.

it should be this way:
var _vendors= query.Where(f => f.Activo == true).OrderBy(o=>o.Nombre).ToList();

Related

How to avoid two embedded cycles in linq query C#

var listOfIds = new List<string>();
var allItems = IEnumerable<Info>();
foreach (var id in collectionIds)
{
listOfIds.AddRange(allItems
.Where(p => p.Data.FirstOrDefault(m => m.Key == "myId").Value == id)
.Select(x => x.Id));
}
I would like to avoid using AddRange but use only Add in this case and maybe use only FirstOrDefault in the place of where to avoid the last Select case.
Is this possible and if yes how?
Assuming your original code is giving you the correct data, specifically you are OK with:
Only concerned that the first item in p.Data contains a matching value and;
p.Data will always contains at least a single element.
Then this code will give you the same output:
var listOfIds = allItems
.Where(p => collectionIds.Contains(p.Data.First(m => m.Key == "myId").Value))
.ToList();
However, if you really do care that any value in p.Data matches, then this would be more appropriate:
var listOfIds = allItems
.Where(p => p.Data.Any(m => m.Key == "myId" &&
collectionIds.Contains(m.Value)))
.ToList();
How about this approach:
var listOfIds = new List<string>();
var allItems = IEnumerable<Info>();
var groupedAllItems = allItems.GroupBy(x => x.Data.FirstOrDefault(m => m.Key == "myId")?.Value ?? "MyIdNotFound");
//collectionIds should be of type HashSet<string> for the contains to be fast
listOfIds.AddRange(groupedAllItems.Where(x => collectionIds.Contains(x.Key)).SelectMany(x => x));

Get product of items in list C# linq

I have a list with people with integerIds who share Tokens I am trying to get the products of each pair of friends id numbers. so friend id 2 and 4 would result in 8 etc.
var FriendsWhoShareTheMostTokens = FriendsWithTheirSharedTokensAmount.Select(x => new
{
FriendIdA = x.FriendTo.FriendID,
FriendIdB = x.FriendFor.FriendID,
SharedCountNumber = x.SharedCount
})
.Where(x => x.SharedCountNumber == FriendsWithTheirSharedTokensAmount.Max(y => y.SharedCount))
.ToList();
// need some code here**
foreach (var pairOffriendsWhoSharetheMostTokens in FriendsWhoShareTheMostTokens)
{
}
Can I accomplish this with Linq or what is the best way to accomplish this?
Edit
The answer is simple
var ProductofGreatestTokenSharers = FriendsWhoShareTheMostTokens.Select(x => new
{
ProductOfIds = x.FriendIdA * x.FriendIdB
}
);
It's really hard to understand what you are trying to achieve with your example.
However, if you want to have the id's and the product, and also obtain the highest SharedCountNumber.
You can probably just do the following
var someResult = someList.Select(x => new
{
FriendIdA = x.FriendTo.FriendID,
FriendIdB = x.FriendFor.FriendID,
SharedCountNumber = x.FriendTo.FriendID * x.FriendFor.FriendID
}) // Projection
.OrderByDescending(x => x.SharedCountNumber) // order the list
.FirstOrDefault(); // get the first
if (someResult != null)
{
Debug.WriteLine($"A : {someResult.FriendIdA}, B : {someResult.FriendIdB}, Product : {someResult.SharedCountNumber}");
}

Using linq to filter List of List

I still don't have a good grasp on LINQ yet, and felt like my code could be optimised so looking for help.
I have a Patient and Med Class, each have a public bool IsSelected. These are wrapped into the PatientMeds and PatientsMeds Classes;
public class PatientMeds
{
public Patient Patient;
public List<Med> Meds;
}
public class PatientsMeds
{
public List<PatientMeds> PatientMedsList;
}
I want to filter these, so if the Patient.IsSelected == false then ignore it, and ignore only the Meds where IsSelected == false;
Now, this code works:
List<PatientMeds> patientMedsList = PatientsMeds.PatientMedsList
.Where(x => x.Patient.IsSelected)
.ToList();
foreach (PatientMeds patientMeds in patientMedsList)
{
var medsToRemove = patientMeds.Meds.Where(m => m.IsSelected == false).ToList();
foreach (Med med in medsToRemove)
{
patientMeds.Meds.Remove(med);
}
}
But it just seems 'clunky'. How can i make it better?
I would use ForEach RemoveAll method
List<PatientMeds> patientMedsList = PatientsMeds.PatientMedsList
.Where(x => x.Patient.IsSelected)
.ToList();
patientMedsList.ForEach(p=> p.Meds.RemoveAll(m=>!m.IsSelected));
You could construct a new list with new PatientMeds instances containing only selected patients and meds:
var selectedPatientsWithSelectedMeds = patientMedsList.Where(p => p.IsSelected)
.Select(p => new PatientMeds
{
Patient = p.Patient,
Meds = p.Meds.Where(m => m.IsSelected).ToList()
})
.ToList();
So the Where(p => p.IsSelected) only selects selected patients, and the Select(p => new PatientMeds { ... } constructs new PatientMeds instances.
Finally p.Meds.Where(m => m.IsSelected).ToList() constructs a new list with only selected meds.
But it's not clear whether constructing new PatientMeds and List<Med> instances is viable. For example at new PatientMeds { ... } you will need to map all properties of PatientMeds.
Try shortening the following foreach loop
foreach (PatientMeds patientMeds in patientMedsList)
{
patientMeds.Meds.RemoveAll(m => m.IsSelected == false);
}
You can try RemoveAll
patientsMeds
.PatientMedsList
.Where(m => m.Patient.IsSelected)
.ToList()
.ForEach(m => m.Meds.RemoveAll(med => !med.IsSelected));
As being reference type, despite you create new list using ToList() method, it will point to same location. So, the result also will be reflected at patientsMeds variable
just use:
var bb = patientMedsList.Where(p => p.Patient.IsSelected).ToList().Select(p => new PatientMeds { Patient = p.Patient, Meds = p.Meds.Where(m => m.IsSelected).ToList() }).ToList();

Linq - Conversion error when simulating an exists expression

Im having a problem with Linq using Lambda Expressions. Im trying to do this select
SELECT L.IDLLAMADO FROM LLAMADOS L WHERE EXISTS (SELECT D.IDLLAMADO FROM DIAGNOSTICO D WHERE D.DESCRIPCION LIKE '%SOME VALUE%')
Some notes:
Im using IQueryable because Im appending joins and where depending on
the parameters of the method.
In the example I mapped only a property in my complex class because the rest are not useful in the example.
diagonostico is a string parameter.
My code is:
DbSet<Llamados> llamados = context.Set<Llamados>();
IQueryable<ComplexLlamadosAfil> query = llamados
.Select(e => new ComplexLlamadosAfil { IdLlamado = e.IdLlamado });
//If some conditions
query = query.Where(e => diagnosticos.Any(d => d.IdLlamado == e.IdLlamado &&
d.Descripcion.Contains(diagnostico)) == true);
There is not compilation error but when i run this i keep getting this error:
The object type
'System.Data.Objects.ObjectQuery`1[GAMP.MO.VW_DIAGNOSTICOS_LLAMADO]'
cannot be converted into
'System.Data.Entity.DbSet`1[GAMP.MO.VW_DIAGNOSTICOS_LLAMADO]'.
I also tried using .TakeWhile() instead of .Where() but no success.
Thanks for reading guys,
Pablo.
well, the message is rather clear, no ?
I would do
//Don't tell that it's a DbSet<Llamados>. You want an IQueryable<Llamados>
IQueryable<Llamados> llamados = context.Set<Llamados>().AsQueryable();
IQueryable<ComplexLlamadosAfil> query = llamados
.Select(e => new ComplexLlamadosAfil { IdLlamado = e.IdLlamado });
//If some conditions
query = query.Where(e => diagnosticos.Any(d => d.IdLlamado == e.IdLlamado &&
d.Descripcion.Contains(diagnostico)) == true);
or just use var
var llamados = context.Set<Llamados>().AsQueryable();
var query = llamados
.Select(e => new ComplexLlamadosAfil { IdLlamado = e.IdLlamado });
//If some conditions
query = query.Where(e => diagnosticos.Any(d => d.IdLlamado == e.IdLlamado &&
d.Descripcion.Contains(diagnostico)) == true);

QueryOver: Dynamically adding IsLike in Where clause

I've this QueryOver where I select Log records where the Logs Name starts with D or F (using wildcards).
conv.InnerTransaction.Session.QueryOver<Log>()
.Where(l => l.DateTime > _datetime)
.And(
l => l.Name.IsLike("D%") || l.Name.IsLike("F%")
)
Instead I would like the name searching to be dynamically using values from a list. How can this be done?
I've tried something like:
var query = conv.InnerTransaction.Session.QueryOver<Log>()
.Where(l => l.DateTime > _datetime);
foreach (var name in _names)
{
query = query.And(l => l.Name.IsLike(name));
}
But that would result in multiple AND statements for each name in the list, whereas It just need to be a OR.
Have you tried Disjunction? I had a similar requirement once, but I had to use Conjunction instead. Disjunction will or multiple conditions together.
var disjunction = new Disjunction();
var query = Session.QueryOver<Log>().Where(l => l.DateTime > _datetime);
foreach (var name in _names)
{
disjunction.Add(Restrictions.On<Log>(log => log.Name).IsLike(name));
}
var queryResult = query.Where(disjunction).List<Log>();

Categories