how to get the linq list having Ids from IEnumerable<Object> - linq

The code below userModel.Carriers is the type of IEnumerable<CarrierModel>.
userModel.Carriers has a list of carriers having Ids. With those Ids, I want to get CarrierDivision usign linq. But, I can't get it right because linq sqlexpression is not compatible with IEnumerable expression.
userModel.Carriers = carriersForRegion.Select(carrier => Mapper.Map<CarrierModel>(carrier))
.ToList();
var carrierDivision = from c in db.CarrierDivision where c.Contains();

collection.Contains will generate .. WHERE CarrierId IN (1, 2, 3) sql query
var carrierIds = userModel.Carriers.Select(carrier => carrier.Id).ToArray();
var divisions = db.CarrierDivision
.Where(division => carrierIds.Contains(division.CarrierId))
.ToArray();
In case db.CarrierDivision returns IEnumerable(not database), then I would suggest to create HashSet of carrier ids.
var carrierIds = userModel.Carriers.Select(carrier => carrier.Id).ToHashSet();
var divisions = db.CarrierDivision
.Where(division => carrierIds.Contains(division.CarrierId))
.ToArray();
With HashSet search executed without extra enumerations - O(1)

Related

LINQ: single list which consists of multiple properties of same type of object collection

var userIds = books.Select( i => new{i.CreatedById,i.ModifiedById}).Distinct();
var lst = from i in userIds select i.CreatedById;
var lst1 = from i in userIds select i.ModifiedById;
var lstfinal = lst.Concat(lst1).Distinct();
any other way to get same result???
here: books is collection of book objects i.e. IEnumerable.
thanks
Alternative solution - SelectMany from array of required properties:
var lstfinal = books.SelectMany(b => new [] { b.CreatedById, b.ModifiedById })
.Distinct();
Or enumerating books collection twice. Union excludes duplicates, so you don't need to call Distinct (I'd go this way):
var lstfinal = books.Select(b => b.CreatedById)
.Union(books.Select(b => b.ModifiedById));

how to use a dynamic variable in orderby clause

am a newbie in linq.. am stuck with one scenario. ie,
i have to sort the search results based on user input.
user inputs are Last Name, First Name and Title. for input 3 drop downs are there and i have to sort result based on the values selected.
i tried
order = Request["orders"].Split(',');
var param = order[0];
var p1 = typeof(Test).GetProperty(param);
param = order[1];
var p2 = typeof(Test).GetProperty(param);
param = order[2];
var p3 = typeof(Test).GetProperty(param);
model.Test = (from tests in model.Test
select tests).
OrderBy(x => p1.GetValue(x, null)).
ThenBy(x => p2.GetValue(x, null)).
ThenBy(x => p3.GetValue(x, null));
but it doesn't works.
i want qry like this
from tests in model.Test
select tests).OrderBy(x => x.lastname).
ThenBy(x => x.firstname).ThenBy(x => x.Title);
order[0]== lastname but how can i use it in the place of OrderBy(x => x.order[0])..?
Thanks in advance.
i solved my case as follows
// list of columns to be used for sorting
List<string>order = Request["orders"].Split(',').ToList();
//map the column string to property
var mapp = new Dictionary<string, Func<Test, string>>
{
{"FirstName", x => x.FirstName},
{"LastName", x => x.LastName},
{"SimpleTitle", x => x.SimpleTitle}
};
//user inputted order
var paras = new List<Func<Test, string>>();
foreach (var para in order)
{
if(!string.IsNullOrEmpty(para))
paras.Add(mapp[para]);
}
//sorting
model.Test= model.Test.OrderBy(paras[0]).ThenBy(paras[1]).ThenBy(paras[2]);
Thanks all,
Actually you are looking for dynamic linq query than you can try out Dynamic LINQ (Part 1: Using the LINQ Dynamic Query Library)
which allow to do like this
it means you can dynamically pass string propertyname to short you collection in orderby function
You can also read about : Dynamic query with Linq
You can compose the expression (any Expression) manually from pieces and then append it to the previous part of query. You can find more info, with example in "Sorting in IQueryable using string as column name".

Where clause in Linq efficiency?

The beginning of my Linq query is below.
Pay attention only to the where clause. Does Linq do the ToLower() only once? Or does it do ToLower() for every element of searchWords?
var products = from d in xElem.Descendants(fileName)
where searchWords.All(t => d.Element(productName).Value.ToLower().Contains(t))
Assuming this is LINQ to Objects, it will absolutely do it (and indeed the Element call) on each element of searchWords. There's nowhere it could really store state to do anything else, implicitly. You can optimize this easily yourself though:
var products = from d in xElem.Descendants(fileName)
let lowerD = d.Element(productName).Value.ToLower()
where searchWords.All(t => lowerD.Contains(t))
Or in a non-query expression you could use a statement lambda:
var products = xElem.Descendants(fileName)
.Where(d => {
string lowerD = d.Element(productName).Value.ToLower();
return searchWords.All(t => lowerD.Contains(t));
})
... // rest of query
Note that there are other ways of performing case-insensitive comparisons which are more robust. For example:
var products = from d in xElem.Descendants(fileName)
let v = d.Element(productName).Value
where searchWords.All(t =>
v.IndexOf(t, StringComparison.CurrentCultureIgnoreCase) != -1)

EntityFramework: Add Where clause to ObjectSet Query to Select on CHILD attributes

The goal is to return a list of PARENT entities, based on attributes of their CHILD ENTITIES
eg Find me all the CASTLES where LADIES_IN_WAITING belong to PRINCESS 'X'
I want to do something like this:
var query = ObjectSet.Include(c => c.LADIES_IN_WAITING);
query = query.Where(p => p.REGION.ToLower().Contains("shrekVille"));
query = query.Where(p => p.LADIES_IN_WAITING.Where(c => c.PRINCESS.Equals("fiona")));
var results = query.ToList();
This is obviously the incorrect syntax but i can't find any clear examples of how to structure the Query.
I am currently resorting to something like this:
var query = ObjectSet.Include(c => c.LADIES_IN_WAITING);
query = query.Where(p => p.REGION.ToLower().Contains("shrekVille"));
// Get the results from the DB using the query built thus far
var results = query.ToList();
// Now filter the list in memory manually
foreach (var castle in results)
{
var matchingParents = new List<CASTLE>();
var matchingChildren = castle.LADIES_IN_WAITING.Where(a => a.PRINCESS.Equals("fiona"));
if (matchingChildren.Count() > 0)
matchingParents.Add(matchingChild);
}
results = matchingParents;
Any suggestions on how to correctly build the Query would be most welcomed!
You probably want to use the Any operator. It returns true if one item in a collection (i.e. 'any' of them) satisfies the predicate.
var query = ObjectSet.Include(c => c.LADIES_IN_WAITING);
query = query.Where(p => p.REGION.ToLower().Contains("shrekVille"));
// filter the query where, for each p,
// any of the LADIES_IN_WAITING have PRINCESS.Equals("fiona") == true
query = query.Where(p => p.LADIES_IN_WAITING.Any(c =>
c.PRINCESS.Equals("fiona"))); var results = query.ToList();
The complementary operator is All, which would filter your query to those results that have all the LADIES_IN_WAITING meeting the PRINCESS.Equals("fiona") criteria.

Groupby and where clause in Linq

I am a newbie to Linq. I am trying to write a linq query to get a min value from a set of records. I need to use groupby, where , select and min function in the same query but i am having issues when using group by clause. here is the query I wrote
var data =newTrips.groupby (x => x.TripPath.TripPathLink.Link.Road.Name)
.Where(x => x.TripPath.PathNumber == pathnum)
.Select(x => x.TripPath.TripPathLink.Link.Speed).Min();
I am not able to use group by and where together it keeps giving error .
My query should
Select all the values.
filter it through the where clause (pathnum).
Groupby the road Name
finally get the min value.
can some one tell me what i am doing wrong and how to achieve the desired result.
Thanks,
Pawan
It's a little tricky not knowing the relationships between the data, but I think (without trying it) that this should give you want you want -- the minimum speed per road by name. Note that it will result in a collection of anonymous objects with Name and Speed properties.
var data = newTrips.Where(x => x.TripPath.PathNumber == pathnum)
.Select(x => x.TripPath.TripPathLink.Link)
.GroupBy(x => x.Road.Name)
.Select(g => new { Name = g.Key, Speed = g.Min(l => l.Speed) } );
Since I think you want the Trip which has the minimum speed, rather than the speed, and I'm assuming a different data structure, I'll add to tvanfosson's answer:
var pathnum = 1;
var trips = from trip in newTrips
where trip.TripPath.PathNumber == pathnum
group trip by trip.TripPath.TripPathLink.Link.Road.Name into g
let minSpeed = g.Min(t => t.TripPath.TripPathLink.Link.Speed)
select new {
Name = g.Key,
Trip = g.Single(t => t.TripPath.TripPathLink.Link.Speed == minSpeed) };
foreach (var t in trips)
{
Console.WriteLine("Name = {0}, TripId = {1}", t.Name, t.Trip.TripId);
}

Resources