Take() takes different values than Skip() skips - c#

I have written two different queries, the first one is supposed to get the first 5 objects, and then the next one is supposed to get the next 5 objects ordered by the purchased value. The problem is that the two values in the middle are the same and when I take the first five objects, and then skip the first five objects and take the next five objects the last object of the first set is the same as the first value of the second set and the object with the same purchased value as this object is never shown. My queries are below.
var query = (from v in db.VideoGames
where v.gamesystem == "PC"
orderby v.purchased descending
select v).Take(5);
var query2 = (from v in db.VideoGames
where v.gamesystem == "PC"
orderby v.purchased descending
select v).Skip(5).Take(5);
I would like to know if there is something that I can do differently to keep this from happening.
Edit: I feel that my explanation may be a little confusing so I am going to add an example given 10 VideoGame objects in a database and there purchased value.
VideoGame1.purchased = 1,
VideoGame2.purchased = 2,
VideoGame3.purchased = 3,
VideoGame4.purchased = 4,
VideoGame5.purchased = 5,
VideoGame6.purchased = 5,
VideoGame7.purchased = 7,
VideoGame8.purchased = 8,
VideoGame9.purchased = 9,
VideoGame10.purchased = 10
Here is what I am receiving
query: VideoGame10, VideoGame9, VideoGame8, VideoGame7, VideoGame5
query2: VideoGame5, VideoGame4, VideoGame3, VideoGame2, VideoGame1
Here is what I want
query: VideoGame10, VideoGame9, VideoGame8, VideoGame7, VideoGame6
query2: VideoGame5, VideoGame4, VideoGame3, VideoGame2, VideoGame1
I do not care if I get VideoGame5 in the first query, just as long as I get both the VideoGame5 object and the VideoGame6 object.

the object with the same purchased value as this object is never shown
It did not click till I read this sentence a few times. Assuming you mean you have data like the following
class Videogames
{
public string Name { get; set; }
public int purchased { get; set; }
public string gamesystem { get; set; }
public Videogames(string name, int purchased)
{
Name = name;
this.purchased = purchased;
gamesystem = "PC";
}
}
static void Main(string[] args)
{
var VideoGames = new List<Videogames>();
VideoGames.Add(new Videogames("A", 1));
VideoGames.Add(new Videogames("B", 2));
VideoGames.Add(new Videogames("C", 2));
VideoGames.Add(new Videogames("D", 3));
var query = (from v in VideoGames
where v.gamesystem == "PC"
orderby v.purchased descending
select v).Take(2);
var query2 = (from v in VideoGames
where v.gamesystem == "PC"
orderby v.purchased descending
select v).Skip(2).Take(2);
}
You are getting results like A, B and B, D...
The problem is you do not have deterministic sorting, when there is a tie it is up to whatever underlying system is performing the orderby (likely SQL server, and this is EF or Similar).
To fix this you must make your sorting system more specific so there is no ambiguous ties for the sorting engine to decide for you.
Changing your queires to
var query = (from v in VideoGames
where v.gamesystem == "PC"
orderby v.purchased descending, v.Name ascending
select v).Take(2);
var query2 = (from v in VideoGames
where v.gamesystem == "PC"
orderby v.purchased descending, v.Name ascending
select v).Skip(2).Take(2);
would fix it. You did not show your model so I had to make up a field Name. In database situations you usualy have some kind of primary key ID field, just make your queries sort by the primary key as the last sorting parameter and you should be fine.

Related

How to Select one element from a linq multiple join table?

var queryInfo = (from p in table1
join q in table2 on p.TABLEID equals q.USERNAME
join b in table3 on p.ORIGINAL_USER equals b.USERNAME
where p.NAME == IdVal
select new
{
p.NAME,
p.ID,
p.EXCHANGE,
p.CREATION,
q.USERNAME,
q_email = q.EMAIL,
q_fullname = q.FULL_NAME,
b_email = b.EMAIL,
p.ORIGINAL_USER,
b_fullname = b.FULL_NAME
});
Name = queryInfo.ToList().ElementAt(0).ToString();
ID = queryInfo.ToList().ElementAt(1).ToString();
exchange = queryInfo.ToList().ElementAt(2).ToString();
Creation = queryInfo.ToList().ElementAt(3).ToString();
AUsername = queryInfo.ToList().ElementAt(4).ToString();
AEmail = queryInfo.ToList().ElementAt(5).ToString();
AFullName = queryInfo.ToList().ElementAt(6).ToString();
EEmail = queryInfo.ToList().ElementAt(7).ToString();
EUsername = queryInfo.ToList().ElementAt(8).ToString();
EFullName = queryInfo.ToList().ElementAt(9).ToString();
The query is correct and working, I'm having problem trying to select and assign one to each declared variable.
I tried
queryInfo.ToList().ElementAt(0).ToString();
but this is not working. What is the proper syntax?
Create a custom class so you can map your resut into
class:
public class User
{
public string Name { get; set; }
public string ID { get; set; }
public string exchange { get; set; }
public string Creation { get; set; }
public string AUsername { get; set; }
public string AEmail { get; set; }
public string AFullName { get; set; }
public string EEmail { get; set; }
public string EUsername { get; set; }
public string EFullName { get; set; }
}
mapping:
User result = (from p in table1
join q in table2 on p.TABLEID equals q.USERNAME
join b in table3 on p.ORIGINAL_USER equals b.USERNAME
where p.NAME == IdVal
select new User()
{
Name = p.NAME,
ID = p.ID,
exchange = p.EXCHANGE,
Creation = p.CREATION,
AUsername = q.USERNAME,
AEmail = q.EMAIL,
AFullName = q.FULL_NAME,
EEmail = b.EMAIL,
EUsername = p.ORIGINAL_USER,
EFullName = b.FULL_NAME
}).FirtstOrDefault();
Materialize query via FirstOrDefault() and retrieve property values:
var queryInfo =
(from p in table1
join q in table2 on p.TABLEID equals q.USERNAME
join b in table3 on p.ORIGINAL_USER equals b.USERNAME
where p.NAME == IdVal
select new
{
p.NAME,
p.ID,
p.EXCHANGE,
p.CREATION,
q.USERNAME,
q_email = q.EMAIL,
q_fullname = q.FULL_NAME,
b_email = b.EMAIL,
p.ORIGINAL_USER,
b_fullname = b.FULL_NAME
})
.FirstOrDefault();
Name = queryInfo?.NAME;
ID = queryInfo?.ID.ToString();
exchange = queryInfo?.EXCHANGE;
Creation = queryInfo?.CREATION.ToString();
AUsername = queryInfo?.USERNAME;
AEmail = queryInfo?.q_email;
AFullName = queryInfo?.q_fullname;
EEmail = queryInfo?.b_email;
EUsername = queryInfo?.ORIGINAL_USER;
EFullName = queryInfo?.b_fullname;
First some background information
Your code is very inefficient.
queryInfo is an IQueryable<...>, meaning that it holds a query: the potential to fetch some data. It does not hold the data itself.
For this, the IQueryable holds an Expression and a Provider. The Expression represents the query in some generic format. The Provider knows who should execute this query (usually a database management system) and what language is used to communicate with this DBMS.
As long as you concatenate LINQ methods that return IQueryable<TResult>, only the Expression changes. The query is not executed, there is no communication with the DBMS. Concatenating this kind of LINQ methods is efficient.
IQueryable also implements IEnumerable. This means, that to execute the query and to enumerate the fetched sequence, at its lowest level you use GetEnumerator() to get the enumerator, and repeatedly call MoveNext() / Current to access the enumerated element:
IQueryable<TResult> query = dbContext.Students.Where(...).OrderBy(...);
// execute the query:
using (IEnumerator<TResult> enumerator = query.GetEnumerator())
{
// and enumerate the fetched data:
while (enumerator.MoveNext())
{
// There is another element, process it:
TResult fetchedElement = enumerator.Current;
ProcessFetchedElement(fetchedElement);
}
}
Well, this is a lot of code. Usually we use high level methods, which deep inside will call GetEnumerator() / MoveNext() / Current:
// execute the query and process the fetched data:
foreach (TResult fetchedElement in query)
{
ProcessFetchedElement(fetchedElement);
}
All LINQ methods that return IQueryable<...> will not execute the query. The other LINQ methods (= the ones that return List<TResult>, TResult, Boolean, etc, anything not IQueryable) will call foreach or deep inside GetEnumerator / MoveNext / Current. These other methods will contact the database to execute the query.
What does this have to do with my question?
Let's look at your code:
var queryInfo = ...
// queryInfo is an IQueryable. The query is not executed yet!
Name = queryInfo.ToList().ElementAt(0).ToString();
// ToList will execute the query and put all data in a List,
// from this List you take the first element and call ToString()
ID = queryInfo.ToList().ElementAt(1).ToString();
// ToList will execute the query again and put all data in a second List,
// from this List you take the second element and call ToString()
etc. You execute the query 10 times. You join the three tables 10 times, you keep only the one with p.Name equal to IdVal and send the remaining data to your process. You do this 10 times.
It would be much more efficient to do this only once:
// execute the query once and put all fetched data in a List
var fetchedData = queryInfo.ToList();
// access the fetched data. Since it is a List, we can use indexes
Name = fetchedData[0].ToString();
Id = fetchedData[1].ToString();
exchange = fetchedData[2].ToString();
Creation = fetchedData[3].ToString();
I don't think that is what you want.
If I look closer at your query, then I see that you join three tables:
var queryInfo = (from p in table1
join q in table2 on p.TABLEID equals q.USERNAME
join b in table3 on p.ORIGINAL_USER equals b.USERNAME
From the joined table (=sequence of rows), you keep only those rows that have p.Name == idVal:
where p.NAME == IdVal
There might be one such element, there might be more, or maybe none.
From each remaining row, you make one new object:
select new
{
p.NAME,
p.ID,
p.EXCHANGE,
...
});
As said before: the result is a query. The query represents the potential to fetch a sequence of objects with properties Name, Id, Exchange, ....
I think, that you want the Name / Id / Exchange / etc from the first element of the sequence
If that is the case, we don't have to fetch all elements, we only need to fetch the first element (if there is one)
var queryInfo = ...
// execute the query, and ask only for the first element.
// In SQL this is something like SELECT TOP 1 ... FROM ...
var fetchedElement = queryInfo.FirstOrDefault();
Now if your query yields one or more elements, you will have only the first one. However, if your query results in an empty sequence, fetchedElement will be null
if (fetchedElement != null)
{
// There is an element with Name == IdVal
Name = fetchedElement.Name;
Id = fetchedElement.Id;
...
}
else
{
// There is no such element; TODO: report to operator?
}
Be aware, that it if the query yields more than one element, it is not guaranteed what the first element of your sequence might be. Therefore, if you expect that in some cases there might be more than one element, consider to order the sequence, so the first element is defined. For instance order by ascending creation date. Sometimes the DBMS does not accept a FirstOrDefault of an unordered sequence.

convert rows to column in entity framwork

how can i convert rows to column in entity framework!?
i have a result like this:
and i want this result:
my entity code i this :
(from loanPerson in context.LoanPersons.AsParallel()
join warranter in context.Warranters.AsParallel() on loanPerson.Id equals warranter.LoanPersonId
where loanPerson.Id == 84829
select new
{
loanPersonId = loanPerson.Id,
waranterId = warranter.WarranterPersonID,
}).ToList();
and number of the row always less than 3 and i want to have 3 column.
please let me know your answer.
tanks.
This query will return the only one row, where waranterIds will contain, at this particular case, three WarranterPersonID values, also this field is of List<int> type, because it's quantity not known at compile time:
var answer = (from loanPerson in context.LoanPersons.Where(x => x.Id == 84829)
join warranter in context.Warranters
on loanPerson.Id equals warranter.LoanPersonId
group warranter by loanPerson.Id into sub
select new
{
loanPersonId = sub.Key,
waranterIds = sub.Select(x => x.LoanPersonId).ToList()
//if you sure, that quantity equals 3,
//you can write this code instead of waranterIds:
//zamen1 = sub.Select(x => x.LoanPersonId).First(),
//zamen2 = sub.Select(x => x.LoanPersonId).Skip(1).First(),
//zamen3 = sub.Select(x => x.LoanPersonId).Skip(2).First()
}).ToList();

C# LINQ statement with joins, group by and having then mapped into list object

I have a model called ElectricityBillSiteExceeding that looks like this:
public class ElectricityBillSiteExceeding
{
public string GroupInvoiceNumber { get; set; }
public int ElectricityBillMainId { get; set; }
public string SiteNo { get; set; }
public decimal BillSiteTotal { get; set; }
public decimal MaximumAmount { get; set; }
}
I want to create a list of this type and use it to feed a grid on one of my pages, the purpose is to show which site has bills that exceed the max amount allowed.
I have written the SQL which will give me this dataset, it looks like this:
SELECT SUM(ElectricityBillSiteTotal),
ebs.ElectricityBillMainId,
SiteNo,
ebm.GroupInvoiceNumber,
es.MaximumAmount
FROM dbo.ElectricityBillSites ebs
LEFT JOIN dbo.ElectricityBillMains ebm
ON ebs.ElectricityBillMainId = ebm.ElectricityBillMainId
LEFT JOIN dbo.ElectricitySites es
ON ebs.SiteNo = es.SiteNumber
GROUP BY ebs.ElectricityBillMainId, SiteNo, ebm.GroupInvoiceNumber, es.MaximumAmount
HAVING SUM(ElectricityBillSiteTotal) <> 0 AND SUM(ElectricityBillSiteTotal) > es.MaximumAmount
I'm now in my repository trying to write the method which will go to the database and fetch this dataset so that I can power my grid for the user to see.
This is where I'm struggling. I have written a basic LINQ statement to select from a couple of tables, however I'm unsure how I can incorporate the group by and having clause from my SQL and also how I can then turn this IQueryable object into my List<ElectricityBillSiteExceeding> object.
What I have so far
public List<ElectricityBillSiteExceeding> GetAllElectricityBillSiteExceedings()
{
var groupedBillSitesThatExceed = from billSites in _context.ElectricityBillSites
join billMains in _context.ElectricityBillMains on billSites.ElectricityBillMainId equals
billMains.ElectricityBillMainId
join sites in _context.ElectricitySites on billSites.SiteNo equals sites.SiteNumber
//TODO: group by total, mainId, siteNo, GroupInv, MaxAmt and Having no total = 0 and total > max
select new
{
groupInv = billMains.GroupInvoiceNumber,
mainId = billMains.ElectricityBillMainId,
siteNo = billSites.SiteNo,
total = billSites.ElectricityBillSiteTotal,
max = sites.MaximumAmount
};
//TODO: Map the result set of the linq to my model and return
throw new NotImplementedException();
}
Can anyone point me in the right direction here?
The correct Linq query for your sql is the following. See Left Join to understand the DefaultIfEmpty and also the notes there about the use of ?. in the following group by.
(About the having - in linq you just provide a where after the group by)
var result = from ebs in ElectricityBillSites
join ebm in ElectricityBillMains on ebs.ElectricityBillMainId equals ebm.ElectricityBillMainId into ebmj
from ebm in ebmj.DefaultIfEmpty()
join es in ElectricitySites on ebs.SiteNo equals es.SiteNumber into esj
from es in esj.DefaultIfEmpty()
group new { ebs, ebm, es } by new { ebs.ElectricityBillMainId, ebs.SiteNo, ebm?.GroupInvoiceNumber, es?.MaximumAmount } into grouping
let sum = grouping.Sum(item => item.ebs.ElectricityBillSiteTotal)
where sum > 0 && sum > grouping.Key.MaximumAmount
orderby sum descending
select new ElectricityBillSiteExceeding
{
GroupInvoiceNumber = grouping.Key.GroupInvoiceNumber,
ElectricityBillMainId = grouping.Key.ElectricityBillMainId,
SiteNo = grouping.Key.SiteNo,
BillSiteTotal = sum,
MaximumAmount = grouping.Key.MaximumAmount
};
The error you get:
An expression tree lambda may not contain a null propagating operator
By reading this I conclude that you have an older versino of the provider and thus replace the group by code from the code above with the following:
let GroupInvoiceNumber = ebm == null ? null : ebm.GroupInvoiceNumber
let MaximumAmount = es == null ? 0 : es.MaximumAmount
group new { ebs, ebm, es } by new { ebs.ElectricityBillMainId, ebs.SiteNo, GroupInvoiceNumber, MaximumAmount } into grouping
Before getting into grouping , you need to be aware that the default join in LINQ is always an INNER JOIN. Take a look at the MSDN page How to: Perform Left Outer Joins. However, in the solution I'm presenting below, I'm using INNER JOINs since you are using fields from the other tables in your grouping and having clauses.
For reference on grouping using LINQ, check out How to: Group Query Results on MSDN.
A solution specific to your case is going to look something like:
public List<ElectricityBillSiteExceeding> GetAllElectricityBillSiteExceedings()
{
var qryGroupedBillSitesThatExceed = from billSites in _context.ElectricityBillSites
join billMains in _context.ElectricityBillMains on billSites.ElectricityBillMainId equals billMains.ElectricityBillMainId
join sites in _context.ElectricitySites on billSites.SiteNo equals sites.SiteNumber
where billSites.ElectricityBillSiteTotal != 0 && billSites.ElectricityBillSiteTotal > sites.MaximumAmount
group new { billMains.GroupInvoiceNumber, billMains.ElectricityBillMainId, billSites.SiteNo, billSites.ElectricityBillSiteTotal, sites.MaximumAmount }
by new { billMains.GroupInvoiceNumber, billMains.ElectricityBillMainId, billSites.SiteNo, billSites.ElectricityBillSiteTotal, sites.MaximumAmount } into eGroup
select eGroup.Key;
var inMemGroupedBillSitesThatExceed = qryGroupedBillSitesThatExceed.AsEnumerable();
var finalResult = inMemGroupedBillSitesThatExceed.Select(r => new ElectricityBillSiteExceeding()
{
BillSiteTotal = r.ElectricityBillSiteTotal,
ElectricityBillMainId = r.ElectricityBillMainId,
GroupInvoiceNumber = r.GroupInvoiceNumber,
MaximumAmount = r.MaximumAmount,
SiteNo = r.SiteNo,
});
return finalResult.ToList();
}
This probably will be enough. You could use AutoMapper. It will trivialize mapping to classes.
var resultList = groupedBillSitesThatExceed
.AsEnumerable() //Query will be completed here and loaded from sql to memory
// From here we could use any of our class or methods
.Select(x => new ElectricityBillSiteExceeding
{
//Map your properties here
})
.ToList(); //Only if you want List instead IEnumerable
return resultList;

LINQ join and orderby issues

OK, I've been banging my head against this for a few days, and after studying LINQ I think I am on the right track. But I have a SQL brain and that is sometimes hard to translate to C#.
I have two arrays, one sorted alphabetically, and the other ordered by ID. I need to order the second array alphabetically. The IDs are the joining factor. I.E. A.ID = P.ID.
Here are my arrays and example values;
private IGenericListItem[] _priceLevels = new IGenericListItem[0];
_priceLevels is in the form of {ID, Name}
{3, A}
{8, B}
{4, C}
{7, D}
{5, E}
{9, F}
{1, G}
Edit: updated this to show _assignmentControls contains a sub array. I didn't make it so excuse the insanity. It actually contains a copy of _priceLevels...
protected ArrayList _assignmentControls = new ArrayList();
_assignmentControls is in the form of {ID, LastPrice, NewPrice, _priceLevels[]}
{1, 1.00, 2.00, _priceLevels}
{2, 1.00, 2.00, _priceLevels}
{3, 1.00, 2.00, _priceLevels}
{4, 1.00, 2.00, _priceLevels}
Part of the problem as that I'm trying to compare/join an ArrayList and an IGenericListItem.
In SQL I would do something like this;
SELECT A.*
FROM _assignmentControls A JOIN _priceLevels P
ON A.ID = P.ID
ORDER BY P.Name
This Returns me an _assignmentControls table sorted by the values in _priceLevels.
In C# LINQ I got this far, but can't seem to get it right;
var sortedList =
from a in _assignmentControls
join p in _priceLevels on a equals p.ID
orderby p.Name
select _assignmentControls;
I am getting red squigglies under join and orderby and the p in p.Name is red.
And A) it doesn't work. B) I'm not sure it will return sortedList as a sorted version of _assignmentControls sorted by _priceLevels.Name.
EDIT: When I hover over "join" I get "The type arguments for the method 'IEnumerable System.Linq.Enumerable.Join(this Enumerable,IEnumerable, Func,Func....'cannot be infered from the query. I am researching that now.
Thanks for looking!
When I hover over "join" I get "The type arguments for the method IEnumerable System.Linq.Enumerable.Join(this Enumerable,IEnumerable, Func,Func.... cannot be infered from the query.
I can explain what is going on here so that you can track it down.
When you say
from firstitem in firstcollection
join seconditem in secondcollection on firstkey equals secondkey
select result
the compiler translates that into:
Enumerable.Join(
firstcollection,
secondcollection,
firstitem=>firstkey,
seconditem=>secondkey,
(firstitem, seconditem)=>result)
Enumerable.Join is a generic method that has four type parameters: the element type of the first collection, the element type of the second collection, the key type, and the result type.
If you're getting that error then one of those four things cannot be deduced given the information you've provided to the compiler. For example, maybe:
The type of the first collection is not actually a sequence.
The type of the second collection is not actually a sequence.
The type of the result cannot be deduced
The two keys are of inconsistent types and there is no unique best type.
That last point is the most likely one. Suppose for example the first key is int and the second key is short. Since every short can be converted to int, int would win, and the second key would be automatically converted to int. Now suppose that the first key type is Giraffe and the second key type is Tiger. Neither is better than the other. C# does not say "oh, they're both kinds of Animal, so let's pick that." Rather, it says that you haven't provided enough information to determine which one you meant; you should cast one of them to Animal and then it becomes clear.
Make sense?
There's a half-hour video of me explaining this feature back in 2006 -- this was back when I was adding the feature in question to the compiler -- so if you want a more in-depth explanation, check it out.
http://ericlippert.com/2006/11/17/a-face-made-for-email-part-three/
UPDATE: I just read your question again more carefully:
Part of the problem as that I'm trying to compare/join an ArrayList and an IGenericListItem.
There's the problem. The type of the sequence cannot be determined from an ArrayList. You should not use ArrayList anymore. In fact, you should not use it in any code written after 2005. Use List<T> for some suitable T.
Your select clause is wrong, it should be like this:
var sortedList =
from a in _assignmentControls
join p in _priceLevels on a equals p.ID
orderby p.Name
select a;
Another issue is that _assignmentControls is of type ArrayList, which has elements of type Object, so the compiler doesn't know the actual type of a, and can't use it as the join criteria since a doesn't have the same type as p.ID.
You should use a List<int> (assuming p.ID is of type int) instead of ArrayList. Another option is to specify the type of a explicitly:
var sortedList =
from int a in _assignmentControls
join p in _priceLevels on a equals p.ID
orderby p.Name
select a;
I think you should write:
var sortedList =
from a in _assignmentControls
join p in _priceLevels on a.ID equals p.ID
orderby p.AnotherValue
select a;
When you write from a in _assignmentControls - you are declaring a variable that refers to current element in a sequance that the operation to be performed on. And when you're calling select - you're projecting element from the sequence. Imagine it like conveyer.
Let me give you some example with dump data:
public class SomeCLass
{
public int ID { get; set; }
public string Name { get; set; }
}
public class AnotherClass
{
public int ID { get; set; }
public int Value { get; set; }
public int AnotherValue { get; set; }
}
public void TestMEthod()
{
List<SomeCLass> _assignmentControls = new List<SomeCLass>()
{
new SomeCLass() { ID = 1, Name = "test"},
new SomeCLass() { ID = 2, Name = "another test"}
};
List<AnotherClass> _priceLevels = new List<AnotherClass>()
{
new AnotherClass() {ID = 1, AnotherValue = 15, Value = 13},
new AnotherClass() {ID = 2, AnotherValue = 5, Value = 13}
};
var sortedList =
//here you're declaring variable a that will be like caret when you going through _assignmentControls
from a in _assignmentControls
join p in _priceLevels on a.ID equals p.ID
orderby p.AnotherValue
select a;
foreach (var someCLass in sortedList)
{
Console.WriteLine(someCLass.Name);
}
}
Result:
another test
test

Get list of child records

I have a database that looks like this:
tbl_Seminar
ID
isActive
tbl_SeminarFees
ID
seminar_id -- foreign key
fee_text
I want to get all seminars that are active (isActive ==1) and a list of the fees associated with that seminar. Each Seminar may have n records in tbl_SeminarFees that are its fees. I am able to return a linq structure that returns me a list of objects that look like this {seminar, SeminarFee} but I wanted to create a nested structure that looks like this:
{seminar, List<SeminarFee>}
What should my linq query look like?
here is my linq currently:
var results = from s in context.Seminar
join p in context.SeminarFees on
s.ID equals p.SeminarID
where s.IsActive == 1
select new
{
Seminar = s,
Fees = p
};
How do I change this to get a list of these: {seminar, List<SeminarFee>}
Thanks
UPDATE
#lazyberezovsky gave me a good idea to use a group join and into another variable. But then how do I loop through the result set. Here is what I have now:
foreach (var seminarAndItsFeesObject in results)
{
//do something with the seminar object
//do something with the list of fees
}
This however gives me the following error:
Argument type 'SeminarFees' does not match the
corresponding member type
'System.Collections.Generic.IEnumerable`1[SeminarFees]'
What am I doing wrong?
Thanks
You can use group join which groups inner sequence items based on keys equality (a.k.a. join..into) to get all fees related to seminar:
var results = from s in context.Seminar
join f in context.SeminarFees on
s.ID equals f.SeminarID into fees // here
where s.IsActive == 1
select new
{
Seminar = s,
Fees = fees
};
You can't call ToList() on server side. But you can map results on client later.
BTW You can define navigation property Fees on Seminar object:
public virtual ICollection<SeminarFee> Fees { get; set; }
In this case you will be able load seminars with fees:
var results = context.Seminar.Include(s => s.Fees) // eager loading
.Where(s => s.IsActive == 1);
var results = from s in context.Seminar
join p in context.SeminarFees on s.ID equals p.SeminarID
where s.IsActive == 1
group p by s into grouped
select new {
Seminar = grouped.Key,
Fees = grouped.ToList()
};

Categories