How get a specific value from a query in Linq - c#

I am just starting learning about Linq. I wrote some examples but there is a doubt that I haven't been able to solve.
I am working with the Northwind database, I just used the tool called SqlMetal in order to make all the modeling.
Right now I just wrote the following query:
var q = from c in db.Customers
from o in c.Orders
where c.City == "London"
select new { c, o };
I know that this query brings to me a resulting set of data that contains all the columns of the Customers and Orders tables for the given condition (c.City == "London"). But my question is:
After executing that query, How can I get the value of the column Customers.CustomerID and Orders.OrderID FROM THE VARIABLE q?
Maybe this is a silly question but I have been struggling with this for a couple hours, thanks in advance.

var theSoleItem = q.First();
theSoleItem.CustomerID
theSoleItem.OrderID
Also, if that was the only columns you cared about, your initial query would be faster with:
select new {c.CustomerID, o.OrderID}
You could also change the names as you go:
select new {CustID = c.CustomerID, OrdID = o.OrderID}
The latter being the only option if rather than directly referencing a property, you reference a method call.

The variable q is now a sequence of anonymous objects that have two objects in it: Customer and Order. You can easy iterate over it:
foreach(var item in q)
{
Console.WriteLine("CustomerID = " + item.CustomerID + " order ID = " + item.OrderID);
}

Related

Group data and retrieve every line of the grouping with Entity Framework

I was thinking that maybe, once the grouped data are retrieved in the C# part, I would be able loop through the list of items that were grouped.
var res = db.Commandes.Where(t => t.idMatiere == mod.idMatiereChoisie).GroupBy(t => t.UA_idCa);
foreach(var group in res)
{
foreach(var groupedLines in group)
{
// Always a single line, this loop is useless
}
}
It seems the logic applied here is more like SQL than C#: the grouping result in a single line and you won't see all the grouped items.
It's not a problem that I can't overcome
Tactic I will use: instead of grouping, I'll just query all the lines, and then, while looping, I will verify if UA_idCa is different form the previous data and that will means the next "group" has been reached.
But I wonder... How does someone normally do this cleanly, if it's possible?
Do you have to query again to retrieve a group's content?
Or is the "Tactic I will use" closer to what's best?
This problem is a matter of the combination of SQL server AND Entity Framework.
Seems like one of the value in the grouped part (a value that is different for all the line inside the group) must be marked as not null.
Because when looking for what could be a key, entity doesn't give a damn about nullable values : they could be unique, they could be never null, EF won't even check that.
Once it is marked as NOT NULL in the sql part, EF suddenly understand that there could multiple different unique values in the grouped part...
So basically This :
ALTER view [dbo].[Commandes] as
SELECT top(50000000)
isnull(ex.unitAdm, '000') UnitAdm
,c.id as idCahier
,isnull(ex.unitAdm, '000') + cast(c.id as nvarchar(6)) as UA_idCa
,c.NomCahier
,[Qte]
,c.prix as PrixCahier
,sc.id, 0 as idSousCahier /* THIS IS WHAT I COULD NOT COMPLETELY RETRIEVE
because it could be null ? */
,sc.NomCahier as sousCahier
,sc.prix as PrixSC
,m.id as idMatiere
,m.Code
,m.NomMatiere
,ep.id as idEpreuve
,ep.Titre
FROM [CahierExamen] cex
join Cahier c on c.id = cex.Fk_Cahier
join Examen ex on cex.FK_Examen = ex.id
join epreuve ep on ex.FK_Epreuve = ep.id
join Matiere m on ep.FK_Matiere = m.id
left join SousCahier sc on c.id = sc.FK_Cahier
order by code, unitAdm, idCahier
GO
As been changed to this:
ALTER view [dbo].[Commandes] as
SELECT top(50000000)
isnull(ex.unitAdm, '000') UnitAdm
,c.id as idCahier
,isnull(ex.unitAdm, '000') + cast(c.id as nvarchar(6)) as UA_idCa
,c.NomCahier
,[Qte]
,c.prix as PrixCahier
,isnull(sc.id, 0) as idSousCahier /* WOW, NOW EF UNDERSTAND
THERE COULD BE MULTIPLE DIFFERENTS VALUES ONCE DATA ARE GROUPED*/
,sc.NomCahier as sousCahier
,sc.prix as PrixSC
,m.id as idMatiere
,m.Code
,m.NomMatiere
,ep.id as idEpreuve
,ep.Titre
FROM [CahierExamen] cex
join Cahier c on c.id = cex.Fk_Cahier
join Examen ex on cex.FK_Examen = ex.id
join epreuve ep on ex.FK_Epreuve = ep.id
join Matiere m on ep.FK_Matiere = m.id
left join SousCahier sc on c.id = sc.FK_Cahier
order by code, unitAdm, idCahier
GO

Linq To Entities, Select multiple sets of data with one query

I've found plenty of info on how to select multiple result sets with stored procedures but nothing substantial on how to do so with a linq query.
For example, I can do sub-queries that return mulitple sets of results with something like
var query = (from school in context.Schools
where school.id == someId
select new
{
subSetA = (from student in context.Students
select student).ToList(),
subSetB = (from building in context.Buildings
select building).ToList(),
}).First();
query.subSetA; //Access subSetA
query.subSetB; //Access subSetB
Which works fine, but what if I just want to select both subSetA and subSetB without querying against the school table? I want to select two separate sets of data that gets sent to the server in one query.
Any information as to how to do this with EF 6 would be great.
Well, I'm sure there are many ways to do this, but if you want to avoid introducing a third DbSet into the mix...
var query = (from s in context.Students.Take(1)
select new
{
subSetA = context.Students.ToList(),
subSetB = context.Buildings.ToList(),
})
Then, you can use query.ToList() or maybe using query.Load() and working with context.Students.Local, etc. would work.

Writing a subquery using LINQ in C#

I would like to query a DataTable that produces a DataTable that requires a subquery. I am having trouble finding an appropriate example.
This is the subquery in SQL that I would like to create:
SELECT *
FROM SectionDataTable
WHERE SectionDataTable.CourseID = (SELECT SectionDataTable.CourseID
FROM SectionDataTable
WHERE SectionDataTable.SectionID = iSectionID)
I have the SectionID, iSectionID and I would like to return all of the records in the Section table that has the CourseID of the iSectionID.
I can do this using 2 separate queries as shown below, but I think a subquery would be better.
string tstrFilter = createEqualFilterExpression("SectionID", strCriteria);
tdtFiltered = TableInfo.Select(tstrFilter).CopyToDataTable();
iSelectedCourseID = tdtFiltered.AsEnumerable().Select(id => id.Field<int>("CourseID")).FirstOrDefault();
tdtFiltered.Clear();
tstrFilter = createEqualFilterExpression("CourseID", iSelectedCourseID.ToString());
tdtFiltered = TableInfo.Select(tstrFilter).CopyToDataTable();
Although it doesn't answer your question directly, what you are trying to do is much better suited for an inner join:
SELECT *
FROM SectionDataTable S1
INNER JOIN SectionDataTable S2 ON S1.CourseID = S2.CourseID
WHERE S2.SectionID = iSectionID
This then could be modeled very similarily using linq:
var query = from s1 in SectionDataTable
join s2 in SectionDataTable
on s1.CourseID equals s2.CourseID
where s2.SectionID == iSectionID
select s1;
When working in LINQ you have to think of the things a bit differently. Though you can go as per the Miky's suggestion. But personally I would prefer to use the Navigational properties.
For example in your given example I can understand that you have at-least 2 tables,
Course Master
Section Master
One Section must contain a Course reference
Which means
One Course can be in multiple Sections
Now if I see these tables as entities in my model I would see navigational properties as,
Course.Sections //<- Sections is actually a collection
Section.Course //<- Course is an object
So the same query can be written as,
var lstSections = context.Sections.Where(s => s.Course.Sections.Any(c => c.SectionID == iSectionID)).ToList();
I think you main goal is, you are trying extract all the Sections where Courses are same as given Section's Courses.

Select all tags that are user in questions asp.net c# EF

There are four tables:
Questions(questionId, question)
QuestionTags(questionTagId, questionId, tagId)
CodingKeys(codingKeyId, codingTypeId ..)
Codings(codingId, codingKeyId, coding ..)
I want to select all question tagIds and their codings (codingKeyId is foreign key of tagId) that are represented in Questions... So if I have 10 different codings in Codings table but only two of them are represented in Questions I want to select only these two.
I tried with join like this:
var query = from qt in context.QuestionTags
join c in context.Codings on qt.tagId equals c.codingKeyId
select new
{
tagId = qt.tagId,
coding = c.coding
};
But the above solution gave me double results. For example, if one tag is included in more than one question, I get the same tag twice (I tried distinct, but that didn't work).
I also tried using Any:
var query= context.QuestionTags
.Where(qt => qt.Questions.QuestionTags.Any(q => q.tagId == qt.tagId))
.Select(qt => new
{
codingKeyId = qt.questionId,
coding = context.Codings.FirstOrDefault(c => c.CodingKeys.codingKeyId == qt.tagId).coding
});
The same thing happened here, I got duplicate results, but Distinct didn't work (don't know why).
However, if I use this SQL statement:
SELECT distinct tagId, coding
FROM QuestionTags
LEFT OUTER JOIN Codings ON codingKeyId LIKE QuestionTags.tagId
WHERE Codings.languageId = 1
I get the right result, but I don't want to write and store a procedure for this. I really wan't to know if I can solve this with EF (linq), and I am also not sure if distinct is the right solution.
Thanks for your help.
You can use group by in order to get just the results you want.
var query = from qt in context.QuestionTags
join c in context.Codings on qt.tagId equals c.codingKeyId
group qt by new {tagId = qt.tagId,coding = c.coding } into element
select new
{
tagId = element.Key.tagId,
coding = element.Key.coding
};
Please mark it as answer if you find it useful
var result = from qt in context.QuestionTags
join c in context.Codings on qt.tagId equals c.codingKeyId
where c.languageId == 1
select new
{
codingKeyId = qt.tagId,
coding = c.coding
};
return result.Distinct()
Ok, like this it is working, but is this the only way to use it with distinct and join... I am not sure if this is the right solution (but it gives me the right result) ... maybe it can be optimized a bit...
Try
var query = from qt in context.Codings
join c in context.QuestionTags on qt.tagId equals c.codingKeyId
select new
{
tagId = qt.tagId,
coding = c.coding
};

DefaultIfEmpty in LINQ-to-SQL join causing duplicates

Here is an extract of my query:
...
join p in dc.PODs on c.ID equals p.Consignment into pg
from pgg in pg.DefaultIfEmpty()
...
What the query should do is get all the 'PODs' associated with a consignment, store it as an IEnumerable object (which seems to work) so I can run through it when querying the main IEnumerable generated from the query.
The problem is, I am getting duplicate main rows with the DefaultIfEmpty line, which only happens when a row has multiple PODs - so it's returning a row for each POD, which is incorrect. If I take out the pg.DefaultIfEmpty() line, it seems to work a bit better, but I still want to get the rows without PODs.
Any ideas guys?
Just want to confirm for your 2nd case, wouldn't the output be without the Two, Four, Five which have none item since it is not an outer join?
One
1 TextBox
Three
3 Refridgerator
3 Bucket
What I tried was use an equivalent WHERE IN for dc.PODS.
....join appraisal in ef_appraisal on application.a_appraisalid equals appraisal.a_appraisalid
where
(from r in ..
select r.r_applicationid).Contains(application.a_id) )
Do share if you have other ideas
Forgive me if I'm off on your intention because I can't see the complete structure of your data or your initial from or final select clause in your query excerpt. So I'm posting what I think is a solution based on your snippet and sample data I constructed. Let me know if I'm off and I'll correct it.
If you want a list of rows of consignments to PODs, with each consignment to POD on its own line, you could do something like this (keep in mind my from and select clause are based on my sample data):
// select the consignment id & name (i made up) and each matching POD
var results = from c in consignments
join p in dc.PODs on c.ID equals p.Consignment into pg
from pgg in pg.DefaultIfEmpty()
select new { ID = c.ID, Name = c.Name, POD = pgg };
// This is just a SAMPLE display just for kicks and grins
foreach (var r in results)
{
Console.WriteLine(r.Name + " " + ((r.POD != null)
? (r.POD.Consignment + " " + r.POD.Description)
: "none"));
}
This query outputs something like:
One 1 TextBox
Two none
Three 3 Refridgerator
Three 3 Bucket
Four none
Five none
However I'm not quite sure I understand your remark:
"The problem is, I am getting
duplicate main rows"
I'm not sure if you're saying you don't want to see the one consignment per purchase per row where each result in the IEnumerable is an item with the consignment and a sequence of PODs, you'd want a query like:
// select the Consignment ID and Name (i made up), and list of PODs
// instead of the individual POD
var results = from c in consignments
join p in dc.PODs on c.ID equals p.Consignment into pg
select new { ID = c.ID, Name = c.Name, PODs = pg };
// This is just a SAMPLE display just for kicks and grins
foreach (var r in results)
{
Console.WriteLine(r.Name + " ");
if (r.PODs.Count() > 0)
{
foreach (var pod in r.PODs)
{
Console.WriteLine("\t" + pod.Consignment + " " + pod.Description);
}
}
else
{
Console.WriteLine("\tNone");
}
}
Where the select is selecting the POD list instead of the individual match, which outputs like this:
One
1 TextBox
Two
None
Three
3 Refridgerator
3 Bucket
Four
None
Five
None

Categories