How to use Join in select statement using linq expression - c#

Hi Have a two tables that have a relationship like below ..
class Boothtable
{
public int BoothId {get;set;}
public string BoothName {get;set;}
public double Price {get;set;}
public int RoomId{get;set;}
}
class RoomTable
{
public int RoomId {get;set;}
public string RoomName{get;set;}
public sting Location {get;set;}
}
I am trying to write a join query using LINQ to join the the boothtable to the roomstable on RoomId and return all properties from the boothtable and only return the RoomName property from the Rooms table. is there anyone that can direct me how to achieve this?
So far i have a linq exp like this but it only returns all properties from the booths table.
var getData = from boothtable in context.Boothtable
join roomtable in context.RoomTable
on boothtable.RoomId equals roomtable.RoomId
where boothtable.BoothId == someId
select boothtable;

If you want to retrieve properties from both you must project an object containing data from both. This uses an anonymous object to do so:
select new { boothtable, roomtable }
If you want to return this collection of anonymous objects from a method then define a custom object with the two properties and instantiate it
select new YourCustomObjet { Booth = boothtable, Room = roomtable }
If you only want some of the properties (missed it at first) then as you project the objects in the examples above just project the specific fields:
select new
{
boothtable.BoothId,
boothtable.BoothName,
boothtable.Price,
roomtable.RoomName
}
Notice that if it is an anonymous object and the desired property names are the same, no need to explicitly define a name

Try this -
var getData = (from boothtable in context.Boothtable
join roomtable in context.RoomTable
on boothtable.RoomId equals roomtable.RoomId
where boothtable.BoothId == someId
select new
{
BoothId = boothtable.BoothId,
BoothName = boothtable.BoothName,
Price = boothtable.Price,
RoomName = roomtable.RoomName
});

Related

LINQ Query to get data from another table

I have two tables
I am trying to write a LINQ Query where I want to select everything in Table 1 but instead of CaseStatusID, I want to return the actual status (Corresponding to CaseStatusID in Table 2).
I have the query but I the error Cannot convert expression type 'System.Collections.Generic.List<CaseId:int, Status:string>' to return type 'System.Collections.Generic.List<Data.Cases>'
I have not been able to find a good example to help me. How can I achieve this?
public List<Case> GetAllCases()
{
var result = (from c in _Context.Cases
join s in _Context.CaseStatus on c.CaseStatusId
equals s.CaseStatusId
select new { c.CaseId, c.CaseStatu.Status }).ToList();
return result;
}
Your return type doesn't match the declared return type List<Case>. When you select new {}, you are actually returning an anonymous object from your linq expression. You can fix it like this:
public List<Case> GetAllCases()
{
var result = (from c in _Context.Cases
join s in _Context.CaseStatus on c.CaseStatusId
equals s.CaseStatusId
select new Case { CaseId = c.CaseId, CaseStatus = c.CaseStatu.Status }).ToList();
return result;
}
Note the new Case{} when selecting your data. You may need to change CaseId and CaseStatus properties to match the actual properties from the Case class.
Update: To Clarify, you would need a Case class that looked minimally like this:
public class Case {
public int CaseId { get; set; }
public string CaseStatus { get; set; }
}
I think the problem is in the select statement where you should return objects list of Case:
public List<Case> GetAllCases()
{
var result = (from c in _Context.Cases
join s in _Context.CaseStatus on c.CaseStatusId
equals s.CaseStatusId
select new Case () { CaseId = c.CaseId, CaseStatusId = c.CaseStatusId }).ToList();
return result;
}
you are creating list of annonymous type and returning list of case. that is the issue

Performing join using linq query in Entity Framework

I'm trying to select some data from a table in my database using a join in a linq query, but I can't seem to grasp how to save it to the list of DTO's that I would like to return.
I've been looking at this post for directions at using the lambda expression: C# Joins/Where with Linq and Lambda but it seems like that guy is trying to accomplish something slightly different than me; I want to compare the value CPR (from the table Coworkers) and the value CPR (From the table Duties) and select all of those where the Projektname (from the table Duties) are equal to the string projektname.
What I've written so far of the method is this:
public List<CoworkerDTO> GetCoworkers(string projektname)
{
_coworkerlist = new List<CoworkerDTO>();
using (var context = new F17ST2ITS2201608275Entities())
{
var dataset =
from co in context.Coworkers
join du in context.Duties on co.CPR equals du.CPR
where du.Projektname == projektname
select new {Coworkers = co};
foreach (var element in dataset.ToList())
{
_coworkerlist.Add(element);
}
}
return _coworkerlist;
}
The CoworkerDTO looks like this:
class CoWorkerDTO
{
public string Fornavn { get; set; }
public string Efternavn { get; set; }
public int Alder { get; set; }
public string CPR { get; set; }
public decimal AntalTimer { get; set; }
}
The table Coworkers has a column that corresponds to each of the properties above, so I guess my question is how to somehow convert the selection that I get into a list of the CoworkerDTOs.
Sorry for the long post, and if my english is a bit confusing, as it's not my first language.
Thanks in advance :)
You should convert Coworkers entity into CoWorkerDTO. You can do it manually (assume properties have same names and types):
var dtos =
from co in context.Coworkers
join du in context.Duties on co.CPR equals du.CPR
where du.Projektname == projektname
select new CoWorkerDTO {
Fornavn = co.Fornavn,
Efternavn = co.Efternavn,
Alder = co.Alder,
CPR = co.CPR,
AntalTimer = co.AntalTimer
};
return dtos.ToList();
Or you can use something like AutoMapper Queryable Extensions to do that projection automatically:
Mapper.Initialize(cfg =>
cfg.CreateMap<Coworkers, CoWorkerDTO>());
And query with projection will look like
var entities =
from co in context.Coworkers
join du in context.Duties on co.CPR equals du.CPR
where du.Projektname == projektname
select co;
return entities.ProjectTo<CoWorkerDTO>().ToList();

display data from 2 joined tables in MVC

I have two tables,and i am performing a left join on them,i want the resultant table to be displayed in my View, any ideas how to do that?
This is my controller section
public Actionresult display()
{
var joindata = (from c in dd.CategoryTbls join n in dd.SubCategoryTbls on c.Id equals n.CategoryId select new { ID=c.Id,CategoryName= c.CategoryName,SubCategoryName=n.SubCategoryName }).ToList();
return(joindata);
}
I cannot display it as a strongly typed view as the resultant table is join of two tables, so any ideas how to do it?
i want the resultant table to be displayed in my View
That's the wrong approach.
In MVC your views do not show 'a table' but they show 'a model'.
That change in wording is the solution: create a class for your joined records and create a strongly-typed View for that Model.
All you want is a View model..Make a class like ViewModelResult or anything like that
public class ViewModelResult
{
public YourTable1 YourTable1{get;set;}
public YourTable1 YourTable2 {get;set;}
}
and then make youir code as below :-
public Actionresult display()
{
ViewModelResult joindata = (from c in dd.CategoryTbls join n in dd.SubCategoryTbls on c.Id equals n.CategoryId select new ViewModelResult { ID=c.Id,CategoryName= c.CategoryName,SubCategoryName=n.SubCategoryName }).ToList();
return view(joindata);
}
and in your view bind ViewModelResult as model and there you can perform whatever you want to like showing data in grid via foreach and etc.
One way would be to use ViewBag
so instead of passing model to the view do this.
ViewBag.Joindata = (from c in dd.CategoryTbls join n in dd.SubCategoryTbls on c.Id equals n.CategoryId select new { ID=c.Id,CategoryName= c.CategoryName,SubCategoryName=n.SubCategoryName }).ToList();
You will then be able to access ViewBag from the view this is very dirty solution.
Example
#ViewBag.Joindata[0].ID
will contain first record.
Other option would be instead of using dynamic object to create model that does represent your viewModel and use strongly typed view, this would be more appropriate solution to your problem.
public class ThatSpecificViewModel
{
public ThatSpecificViewModel(int id, string categoryName, string subCategoryName)
{
this.ID = id;
this.CategoryName = categoryName;
this.SubCategoryName = subCategoryName;
}
public int ID { get; set; }
public string CategoryName { get; set; }
public string SubCategoryName { get; set; }
}
and select it this way
var joindata = (from c in dd.CategoryTbls join n in dd.SubCategoryTbls on c.Id equals n.CategoryId select new ThatSpecificViewModel(c.Id,c.CategoryName,n.SubCategoryName )).ToList();

Query and Assignment in a Single Step

I have a class that has 3 properties:
class Three
{
int ID { get; set ;}
string Name { get; set; }
double Value { get; set; }
}
I then have a linq query that returns a Queryable<Three> but only ID and Name are defined within the table.
var three = from t in db.Threes
select t;
three = { {ID=1, Name="A", Value=0},{ID=2, Name="B", Value=0},...}
So Value is not defined within the db.Threes table so it defaults to 0 as doubles do. I then iterate over each item in var three to set Value based upon another table:
for (int i = 0; i < three.Count(); i++)
{
three[i].Value = (from v in db.Values
where v.ThreeID = i.ID
select v.Value).First();
}
return three;
The Queryable<Three> three now contains definitions for .Value:
three = { {ID=1, Name="A", Value=99},{ID=2, Name="B", Value=100},...}
The key thing that I'm trying to do is to still return a Queryable<Three>, but to also set the Value property.
Is there a better way to do this instead of using a for loop?
I'd like to be able to extend this to any class with a Value property that is assigned from another table; suppose I have a class Four:
class Four
{
int ID {get; set;}
string Name {get; set;}
DateTime Date {get; set;}
double Value {get; set;}
}
The first query would populate with ID, Name and Date and I still want to be able to assign Value. I feel like there is a better way to do this with linq that I just can't come up with.
Edit: suppose I'm calling db.GetTable<T> and Three and Four are really generic arguments that implement a .Value interface. I can't explicitly instantiate a generic type because I would have to hard code the properties.
I think you are looking for join. You are assigning values from another table whose id is the same as the Three table.
You can build back a Three object like this:
var three = from t in db.Threes
join v in db.Values on t.ID equals v.ThreeID
select new Three{
ID = t.ID,
Name = t.Name,
Value = v.Value
};
What you were doing before by looping, that is a performance hit. What happens is that you called to the database to loop it, then for each loop, you make another call back to the database. If your tables are linked by those Ids, then using this code makes 1 single database call and no in memory looping.
What about a simple join, assuming you have some common key?
var things = from t in db.Threes
join v in db.Values on t.SomeId equals v.SomeId
select new Three { ID = t.ID,
Name = t.Name,
Value = v.Value
};

How do I return data from joined tables through subsonic's objects?

I'm using ActiveRecord on Subsonic 3 and I effectively want to do this:
select * from foo
left outer join bar on bar.Id = foo.barId
where foo.someProperty = 2
I've written a stored procedure to fetch the data but Subsonic has only created objects to hold the columns from foo and bar.
What's the best way of returning the data into a single object so I can just bind it. Ideally I want it to be in a list<> but without writing my own class, there doesn't seem to be a way provided by subsonic.
You have a couple options here...
You could create a database view that does your join, and have SubSonic generate a data type for your view, then your select would be just like selecting from any other table.
Alternatively, you could use a Linq expression to do the join into an anonymous or dynamic type (if you are using .net 4) For example:
public List<dynamic> LoadData(int id)
{
var data = from f in db.Foo
from b in db.Bar.Where(x => x.Id == f.BarId).DefaultIfEmpty()
where f.SomeProperty == id
select new
{
SomeProperty = f.Something,
AnotherProperty = b.SomethingElse
};
return data.Cast<dynamic>().ToList();
}
Of course another alternative is to do the Linq expression above, but define your own class to hold the returned data, and select into it.
public class MyData
{
public string SomeProperty { get; set; }
public string AnotherProperty { get; set; }
}
public List<MyData> LoadData(int id)
{
var data = from f in db.Foo
from b in db.Bar.Where(x => x.Id == f.BarId).DefaultIfEmpty()
where f.SomeProperty == id
select new MyData()
{
SomeProperty = f.Something,
AnotherProperty = b.SomethingElse
};
return data.ToList();
}

Categories

Resources