Performing join using linq query in Entity Framework - c#

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();

Related

Need to convert Left join SQL to linq query - help appreciated

Here is my code the issue I have is the less than comparison in the On clause ... Since Linq doesn't allow this .... Migrating down into the where clause wont work as I am comparing one of the fields to null.
Here is the sql query (THE a.UserID= is hardcoded for now)
SELECT A.Policy, A.Comments, A.EventDTTM, A.Status, A.Reason, A.FollowUp
FROM PP_PolicyActivity A
LEFT JOIN PP_PolicyActivity B
ON(A.Policy = B.Policy AND A.EventDTTM < B.EventDTTM)
WHERE A.UserID = 'Ixxxxxx'
AND B.EventDTTM IS NULL AND a.status = 'open - Pending'
order by A.EventDTTM DESC
I need the result set from the above query as an IEnumerable list to populate a view
I'm tasked with rebuilding an old VB ASP NET that has a set of standing production databases behind it ... i don't have the option of changing the db design. I connecting to the server and database and this query was going against a table on that database.. the model also reflects the layout of the actual table.
The problem is with A.EventDTTM < B.EventDTTM - I can't move this to the where clause as I also have to deal with B.EventDTTM IS NULL in the where clause.
I need to retool the query someway so that it is 'linq' friendly
public class PolicyActivityModel
{
public string Policy { get; set; }
public int PolicyID { get; set; }
public string Status { get; set; }
public string Reason { get; set; }
public string Comments { get; set; }
public DateTime EventDTTM { get; set; }
public string UserID { get; set; }
public DateTime FollowUp { get; set; }
}
Company policy prohibits me from showing the connection string.
I am extremely new to Linq, Any help greatly appreciated
thank you
You can use the navigation property after you get the policy from the database.
var policy = DbContext.First(x => x.Id == 1000);
var otherPolicies = policy.ConnectedPolicies.Where(p => ...);
It's weird being a self-join but this is the most direct translation to Linq:
var query = from leftPP in PP_PolicyActivity
join rightPP in PP_PolicyActivity
on new { Policy = leftPP.Policy, EventDTTM = leftPP.EventDTTM }
equals new { Policy = rightPP.Policy, EventDTTM = rightPP.EventDTTM }
into pp from joinedRecords.DefaultIfEmpty()
where leftPP.UserId == 1
&& leftPP.EventDTTM < rightPP.DTTM)
&& rightPP.EventDTTM == null
&& leftPP.status = "open - Pending"
select new
{
leftPP,
rightPP
}
I free typed this, without models or Intellisense, thus there might be some smaller errors.
You could add the order by in that clause, but it's also still an IQUeryable, so I'd leave it.
And then, to get a List of models:
var results = query.OrderByDescending(x => x.EventDTTM).ToList();
The actual join is lines 2,3,4 and 5. It's verbose and "backwards" from SQL, and most importantly uses anonymous types. Accessing indidual properties will look something like:
results[0].leftPP.PolicyId

c# sqlite inner join

I am creating a Xamarin Cross Platform app in VS2017 that uses an SQLite database and I am trying to work out how to perform a query using an inner join. I am using the sqlite-net-pcl NuGet package.
I created the databse using DB Browser for SQLite. I have 2 simple tables.
class Crime
{
[PrimaryKey, AutoIncrement]
public int Id {get; set; }
[NotNull]
public string Name { get; set; }
[NotNull]
public int Legislation { get; set; }
}
class Legislation
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
[NotNull]
public string Title { get; set; }
}
Using DB Browser I have a foreign key set up on Crime.Legislation linked to Legislation.Id.
I am easily able to query a single table and populate a list using the code below.
public partial class LegislationListPage : ContentPage
{
private SQLiteAsyncConnection _connetion;
private ObservableCollection<Legislation> _legislations;
public LegislationListPage ()
{
InitializeComponent ();
_connetion = DependencyService.Get<ISQLiteDb>().GetConnection();
}
protected override async void OnAppearing()
{
await _connetion.CreateTableAsync<Legislation>();
var legislations = await _connetion.Table<Legislation>().OrderBy(x => x.Title).ToListAsync();
_legislations = new ObservableCollection<Legislation>(legislations);
legislationList.ItemsSource = _legislations;
}
}
What I want to do on another page is run a query that returns the Name column from Crime and the Title column from Legislation.
I can achieve this in SQL in DB Browser using
select c.Name, l.Title from Legislation as l inner join Crimes as c on l.Id = c.Legislation
However I don't know how to do this using c# as I have been doing with previous queries. I can't find any .join methods or anything similar. I'm hoping to store the results in a list based on a class that is created on the fly, but I'm not sure if this is possible so I'm happy to create a new class to hold the result of the two strings that will be returned. The end goal is just to populate a list with the results.
If someone could point me in the right direction that would be great.
Thanks in advance.
Ok I managed to find a solution. Quite simple really. I couldn't find a .join method cos i hadn't been 'using' System.Linq.
There are two ways of doing it. Using query syntax and lambda. Lambda is what I was hoping to find so I'm pleased I got it working.
For anyone else looking for something similar here is the two ways I
// First I put both tables into separate lists ( var crimes and var legislation) using the
// way shown in my question. Code for that is omitted here
//Query style
var crimesListItems = from c in crimes
join l in legislations on c.Legislation equals l.Id
select new { c.Name, l.Title };
// Lambda style
var crimesListItems = crimes.Join(
legislations,
c => c.Legislation,
l => l.Id,
(c, l) => new {c.Name, l.Title} );
Credit to Jeremy Clark and his tutorial at https://www.youtube.com/watch?v=tzR2qY6S4yw

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

How to use Join in select statement using linq expression

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
});

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