have join multiple table and get the output in DataRow in LINQ - c#

HI,
I have a scenario where i have join multiple table and get the output in DataRow(All the Rows return by the query).
SQL Query:
SELECT Fr.InterCodeId
FROM
CodeShareInterline Fr,
Airline A,Zone Z #
WHERE
A.AirlineId = Fr.AirlineId
And Fr.ContractId=Z.ContractId
I know how to perform join in LINQ but how can i select all the column(Rows) in select statement of LINQ.

var result = from fr in dataContext.CodeShareInterline
from a in dataContext.AirLine
from z in dataContext.Zone
where a.AirlineId == fr.AirlineId && fr.ContractId == z.ContractId
select new
{
Interline = fr,
AirLine = a,
Zone = z
};
The anonymous type contains all data you want, you can easily visit one column by:
result.FirstOrDefault().Zone.SomeField

This is untested but something close to this should work. Assuming your data context is call Context. This is a translation of what you have above.
var o = from fr in Context.CodeShareInterline
join a from Context.Airline on a.AirlineId == fr.AirlineId
join z from Context.Zone on fr.ContactId == z.ContactId
select fr.InterCodeId;
If you want to select all of the data then you need to do something like this.
var o = from fr in Context.CodeShareInterline
join a from Context.Airline on a.AirlineId == fr.AirlineId
join z from Context.Zone on fr.ContactId == z.ContactId
select new {
Interline = fr,
AirLine = a,
Zone = z
};

Related

How to add less than or equal to condition in linq inner join

We have two objects, Dates and ActiveEvents. Want to perform inner join on these with less than or equal to condition in linq. Same as ref of below SQL where consider #Tables are C# objects
Select A. from #Activities A
Inner Join #Dates D ON A.ActivityDate <= D.ProcessDate
Tried with below but it's not giving correct results.
var filteredActivity = (from e in ActiveEvents
from p in dates
where e.ActivityDate <= p.Date
select new ActiveEvent
{
ActivityDate = p.Date,
EventId = e.EventId
}).ToList();
And
var filteredActivity = (from e in ActiveEvents
from p in dates.Where(r => e.ActivityDate <= r)
select new ActiveEvent
{
ActivityDate = p.Date,
EventId = e.EventId
}).ToList();
Can you please suggest any better way to do this?
You can try this way
var filteredActivity = (from e in ActiveEvents
join p in dates
where e.ActivityDate <= p.ProcessDate
select new ActiveEvent
{
ActivityDate = p.Date,
EventId = e.EventId
}).ToList();
P/s: Ideally, between 2 tables should contain the foreign key to join like this join p in dates on e.Key equals p.ForeignKey
Based on your example, the query is filtering on ProcessDate but your linq query is filtering on p.Date. Are those the same field? The first example you gave should be correct.

How to check available hotel rooms

I am making a hotel reservation system in windows form by using SQL with LINQ. I have tables such as reservation tabel and room table. In reservation table I have checkin and checkout dates. I have no problem to show those rooms from reservation table in a specific date, but I don't know how to show rooms that are available on specific dates. I don't how to compare or filter out RoomsId from reservation table and room table.
Here is how I am getting rooms from reservation table on a specific date (checkin and checkout):
DateTime StartDateWantToBook = Convert.ToDateTime(dateTimePicker1.Value.ToString());
DateTime EndDateWantToBook = Convert.ToDateTime(dateTimePicker2.Value.ToString());
var ReservedRooms = (from u in db.Room join b in db.Reservation on u.RoomId equals b.RoomId join f in db.Floor on u.FloorId equals f.FloorId join ty in db.RoomType on u.RoomTypeId equals ty.RoomTypeId where StartDateWantToBook <= b.EndDate && b.StartDate <= EndDateWantToBook
select new {
RomId = b.RoomId,
Floor = f.FloorName,
RommsNr = u.RumNummer,
Room_Type = ty.AmountRomms
// But Here by somehow I think I have to run
// another Linq query to filter RoomsId and show only those who do not exists in Reservation table.
}
).ToList();
dataGridView1.DataSource = ReservedRooms;
So the question is How to show all rooms in Rooms table that do not exist in Reservartionroom in a specific dates. Thank you again!
This must work for you.
var AvailebleRooms = (from u in db.Room
where (!u.Reservation.Any(b => b.EndDate >= StartDateWantToBook && b.StartDate <= EndDateWantToBook))
select u).ToList();
i think you need left outer join AllRooms and ReservedRooms to get rooms only using where clause with specific dates
You need to select AllRooms, ReservedRooms in a specific date and filter AllRoom by list reservartion. That's my Idea, maybe contains is wrong.
DateTime StartDateWantToBook = Convert.ToDateTime(dateTimePicker1.Value.ToString());
DateTime EndDateWantToBook = Convert.ToDateTime(dateTimePicker2.Value.ToString());
var AllRooms = (from u in db.Room join b in db.Reservation on u.RoomId equals b.RoomId join f in db.Floor on u.FloorId equals f.FloorId join ty in db.RoomType on u.RoomTypeId equals ty.RoomTypeId select new {
RomId = b.RoomId,
Floor = f.FloorName,
RommsNr = u.RumNummer,
Room_Type = ty.AmountRomms
// But Here by somehow I think I have to run
// another Linq query to filter RoomsId and show only those who do not exists in Reservation table.
}).ToList();
var ReservedRooms = (from u in db.Room join b in db.Reservation on u.RoomId equals b.RoomId join f in db.Floor on u.FloorId equals f.FloorId join ty in db.RoomType on u.RoomTypeId equals ty.RoomTypeId where StartDateWantToBook <= b.EndDate && b.StartDate <= EndDateWantToBook select new {
RomId = b.RoomId,
Floor = f.FloorName,
RommsNr = u.RumNummer,
Room_Type = ty.AmountRomms
// But Here by somehow I think I have to run
// another Linq query to filter RoomsId and show only those who do not exists in Reservation table.
}).ToList();
var result = AllRoom.Except(ReservedRooms);
dataGridView1.DataSource = ReservedRooms;

How to perform a left join with an additional filtering in LINQ to entities?

I have several tables, the main one is called DefectRecord, others are called DefectArea, DefectLevel...etc and the one called DefectAttachment. And this problem is about joining DefectRecord with other tables to get a ViewModel for further use. What the hard part I am facing is about the DefectAttachment table.
DefectRecord has a 1-to-many relation with DefectAttachment. While there may be NO attachment at all for one defect record, there may be multiple attachments.
Logically I tried to perform a left join among DefectRecord & DefectAttachment, but there is one more requiredment:
If there is multiple attachments, select ONLY the oldest one(i.e. the
one with oldest CreatedDate field value)
I am stuck at this requirement, how can I perform this with LINQ-to-Entities? Below is the code of what I have now:
var ret = (from dr in defectRecordQuery
join ft in filterQuery on dr.FilterID equals ft.FilterID
join l in levelQuery on dr.LevelID equals l.LevelID
join a in attachmentQuery on dr.DefectRecordID equals a.DefectRecordID into drd
from g in drd.DefaultIfEmpty()
select new DefectRecordViewModel
{
DefectRecordCode = dr.Code,
DefectAttachmentContent = g == null ? null : g.FileContent,
LookupFilterName = ft.FilterName,
}).ToList();
The *Query variable are the IQueryable object which get the full list of corresponding table.
Group your results by the Code and FilterName and then for the content take that of the item in the group that has the oldest date
var ret = (from dr in defectRecordQuery
join ft in filterQuery on dr.FilterID equals ft.FilterID
join l in levelQuery on dr.LevelID equals l.LevelID
join d in attachmentQuery on dr.DefectRecordID equals d.DefectRecordID into drd
from g in drd.DefaultIfEmpty()
group g by new { dr.Code, ft.FilterName } into gg
select new DefectRecordViewModel
{
DefectRecordCode = gg.Key.Code,
DefectAttachmentContent = gg.OrderByDescending(x => x.CreateDateTime).FirstOrDefault() == null? null: gg.OrderByDescending(x => x.CreateDateTime).FirstOrDefault().FileContent,
LookupFilterName = gg.Key.FilterName,
}).ToList();
If using C# 6.0 or higher then you can do:
DefectAttachmentContent = gg.OrderByDescending(x => x.CreateDateTime)
.FirstOrDefault()?.FileContent,

left join in Linq query

I'm trying to do a left join, not an inner join in a linq query. I have found answers related to using DefaultIfEmpty() however I can't seem to make it work. The following is the linq query:
from a in dc.Table1
join e in dc.Table2 on a.Table1_id equals e.Table2_id
where a.Table1_id == id
orderby a.sort descending
group e by new
{
a.Field1,
a.Field2
} into ga
select new MyObject
{
field1= ga.Key.Field1,
field2= ga.Key.Field2,
manySubObjects = (from g in ga select new SubObject{
fielda= g.fielda,
fieldb= g.fieldb
}).ToList()
}).ToList();
The query only gives me the rows from table 1 that have a corresponding record in table 2. I would like every record in table 1 populated into MyObject and a list of 0-n corresponding records listed in manySubObjects for each MyObject.
UPDATE:
I tried the answer to the question that is a "possible duplicate", mentioned below. I now have the following code that does give me one record for each item in Table1 even if there is no Table2 record.
from a in dc.Table1
join e in dc.Table2 on a.Table1_id equals e.Table2_id into j1
from j2 in j1.DefaultIfEmpty()
where a.Table1_id == id
orderby a.sort descending
group j2 by new
{
a.Field1,
a.Field2
} into ga
select new MyObject
{
field1= ga.Key.Field1,
field2= ga.Key.Field2,
manySubObjects = (from g in ga select new SubObject{
fielda= g.fielda,
fieldb= g.fieldb
}).ToList()
}).ToList();
However, with this code, when there is no record in table2 I get "manySubObject" as a list with one "SubObject" in it with all null values for the properties of "SubObject". What I really want is "manySubObjects" to be null if there is no values in table2.
In reply to your update, to create the null listing, you can do a ternary in your assignment of manySubObjects.
select new MyObject
{
field1= ga.Key.Field1,
field2= ga.Key.Field2,
manySubObjects =
(from g in ga select g).FirstOrDefaut() == null ? null :
(from g in ga select new SubObject {
fielda= g.fielda,
fieldb= g.fieldb
}).ToList()
}).ToList();
Here is a dotnetfiddle that tries to do what you're attempting. https://dotnetfiddle.net/kGJVjE
Here is a subsequent dotnetfiddle based on your comments. https://dotnetfiddle.net/h2xd9O
In reply to your comments, the above works with Linq to Objects but NOT with Linq to SQL. Linq to SQL will complain that it, "Could not translate expression ... into SQL and could not treat as a local expression." That's because Linq cannot translate the custom new SubObject constructor into SQL. To do that, you have to write more code to support translation into SQL. See Custom Method in LINQ to SQL query and this article.
I think we've sufficiently answered your original question about left joins. Consider asking a new question about using custom methods/constructors in Linq to SQL queries.
I think the desired Result that you want can be given by using GroupJoin()
The code Below will produce a structure like so
Field1, Field2, List < SubObject > null if empty
Sample code
var query = dc.Table1.Where(x => Table1_id == id).OrderBy(x => x.sort)
.GroupJoin(dc.Table2, (table1 => table1.Table1_id), (table2 => table2.Table2_id),
(table1, table2) => new MyObject
{
field1 = table1.Field1,
field2 = table1.Field2,
manySubObjects = (table2.Count() > 0)
? (from t in table2 select new SubObject { fielda = t.fielda, fieldb = t.fieldb}).ToList()
: null
}).ToList();
Dotnetfiddle link
UPDATE
From your comment I saw this
ga.Select(g = > new SubObject(){fielda = g.fielda, fieldb = g.fieldb})
I think it should be (depends on how "ga" is built)
ga.Select(g => new SubObject {fielda = g.fielda, fieldb = g.fieldb})
Please update your question with the whole query, it will help solve the issue.
** UPDATE BIS **
sentEmails = //ga.Count() < 1 ? null :
//(from g in ga select g).FirstOrDefault() == null ? null :
(from g in ga select new Email{
email_to = g.email_to,
email_from = g.email_from,
email_cc = g.email_cc,
email_bcc = g.email_bcc,
email_subject = g.email_subject,
email_body = g.email_body }).ToList()
Should be:
sentEmails = //ga.Count() < 1 ? null :
((from g in ga select g).FirstOrDefault() == null) ? null :
(from g in ga select new Email{
email_to = g.email_to,
email_from = g.email_from,
email_cc = g.email_cc,
email_bcc = g.email_bcc,
email_subject = g.email_subject,
email_body = g.email_body }).ToList()
Checks if the group has a First, if it doesn't the group doesn't have any records so the Action.Name for a Time Stamp has no emails to send. If the First isn't null the loop throw the group elements and create a list of Email,
var results =
(
// Use from, from like so for the left join:
from a in dc.Table1
from e in dc.Table2
// Join condition goes here
.Where(a.Id == e.Id)
// This is for the left join
.DefaultIfEmpty()
// Non-join conditions here
where a.Id == id
// Then group
group by new
{
a.Field1,
a.Field2
}
).Select(g =>
// Sort items within groups
g.OrderBy(item => item.sortField)
// Project required data only from each item
.Select(item => new
{
item.FieldA,
item.FieldB
}))
// Bring into memory
.ToList();
Then project in-memory to your non-EF-model type.

Get Count from one value in three table linq2sql select?

I just want the apartment complex count along with the other values. Only adding the count breaks the code. The error I get is "Sequence operators not supported for type 'System.String'." I have also tried changing apartCount to an int with no luck. Any help would be appreciated
using (var db = new DataClasses2DataContext())
{
var zips = (from s in db.ZipCodeServiceAvailabilities
join b in db.ZipCodeBoundaries on s.ZipCode equals b.ZipCode
join a in db.pdx_apart_views on s.ZipCode equals a.Zip_Code
where (s.IsServiced == 1 && b.Ordering % 10 == 0)
orderby b.ZipCode
select new
{
zipCode = b.ZipCode.Trim(),
latitude = b.Latitude,
longitude = b.Longitude,
apartCount = a.Apartment_complex.Count()
}).ToArray();
}
I think you miss group by clause in your query.
or you can use corolated sub query in select clause. please explain your question more

Categories