C# Entity Framework join tables - c#

I am trying to get the same results as with a SQL query using Entity Framework method syntax.
SQL query :
select
mr.*, mrf.userId as RequesterUserId, mrt.UserId as ReceiverUserId
from
MoneyRequests mr
inner join
MoneyReqFrom mrf on mr.MoneyRequestId = mrf.MoneyRequestId
inner join
MoneyReqTo mrt on mr.MoneyRequestId = mrt.MoneyRequestId
where
mr.MoneyRequestId = 'acfc8008-4cf7-47ec-a3fe-0fe245af77cc'
EF Linq method syntax :
var moneyreqResponse = context.MoneyRequests
.Join(context.MoneyReqFroms,
mr => mr.MoneyRequestId,
mrf => mrf.MoneyRequestId,
(mr, mrf) => new
{
MoneyRequestId = mr.MoneyRequestId,
Amount = mr.Amount,
RequestType = mr.RequestType,
CreationDate = mr.CreationDate,
RequesterUserId = mrf.UserId
})
.Join(context.MoneyReqTos,
mr => mr.MoneyRequestId,
mrt => mrt.MoneyRequestId,
(mr, mrt) => new
{
MoneyRequestId = mr.MoneyRequestId,
Amount = mr.Amount,
RequestType = mr.RequestType,
CreationDate = mr.CreationDate,
ReceiverUserId = mrt.UserId,
Email = mrt.Email
})
.Where(fullEntry => fullEntry.MoneyRequestId == "acfc8008-4cf7-47ec-a3fe-0fe245af77cc")
.ToList();
I retrieve the data from the database except the column RequesterUserId.
Do you know why?
Thanks

Your query returns a MoneyRequests type, which I belive does not contain RequesterUserId.
You should define a new type with all the properties you need (those returned by the join) and add it to your DbContext.
Also probably you want to mark your new type as keyless

Related

Linq Join query returning empty dataset

I am using below code to join two tables based on officeId field. Its retuning 0 records.
IQueryable<Usage> usages = this.context.Usage;
usages = usages.Where(usage => usage.OfficeId == officeId);
var agencyList = this.context.Agencies.ToList();
var usage = usages.ToList();
var query = usage.Join(agencyList,
r => r.OfficeId,
a => a.OfficeId,
(r, a) => new UsageAgencyApiModel () {
Id = r.Id,
Product = r.Product,
Chain = a.Chain,
Name = a.Name
}).ToList();
I have 1000+ records in agencies table and 26 records in usage table.
I am expecting 26 records as a result with chain and name colums attached to result from agency table.
Its not returning anything. I am new to .net please guide me if I am missing anything
EDIT
#Tim Schmelter's solution works fine if I get both table context while executing join. But I need to add filter on top of usage table before applying join
IQueryable<Usage> usages = this.context.Usage;
usages = usages.Where(usage => usage.OfficeId == officeId);
var query = from a in usages
// works with this.context.usages instead of usages
join u in this.context.Agencies on a.OfficeId equals u.OfficeId
select new
{
Id = a.Id,
Product = a.Product,
Chain = u.Chain,
Name = u.Name
};
return query.ToList();
Attaching screenshot here
same join query works fine with in memory data as you see below
Both ways works fine if I add in memory datasource or both datasource directly. But not working if I add filter on usages based on officeId before applying join query
One problem ist that you load all into memory first(ToList()).
With joins i prefer query syntax, it is less verbose:
var query = from a in this.context.Agencies
join u in this.context.Usage on a.OfficeId equals u.OfficeId
select new UsageAgencyApiModel()
{
Id = u.Id,
Product = u.Product,
Chain = a.Chain,
Name = a.Name
};
List<UsageAgencyApiModel> resultList = query.ToList();
Edit: You should be able to apply the Where after the Join. If you still don't get records there are no matching:
var query = from a in this.context.Agencies
join u in this.context.Usage on a.OfficeId equals u.OfficeId
where u.OfficeId == officeId
select new UsageAgencyApiModel{ ... };
The following code can help to get the output based on the ID value.
Of course, I wrote with Lambda.
var officeId = 1;
var query = context.Agencies // your starting point - table in the "from" statement
.Join(database.context.Usage, // the source table of the inner join
agency => agency.OfficeId, // Select the primary key (the first part of the "on" clause in an sql "join" statement)
usage => usage.OfficeId , // Select the foreign key (the second part of the "on" clause)
(agency, usage) => new {Agency = agency, Usage = usage }) // selection
.Where(x => x.Agency.OfficeId == id); // where statement

Distinct method does not work Entity Framework

How do I get randomly similar data
me tried to merge different ones in the first stage but Different function does not work,
var turler= (from x in db.bird_table_ad
join e in db.kus_resim on x.tr_x equals e.kus_tur
where x.aile == item
select new GozlemTurleri
{
id = x.id,
kod = x.kod,
tr_x = x.tr_x,
en_x = x.en_x,
lt_x = x.lt_x,
turfotourl="image_resize.phpad="+e.altDIR+"/"+e.resim+"&yon="+(e.galeri=="fg"?"2":"HD2"),
aile = x.aile,
gfoto = x.gfoto
}).Distinct().ToList();
If you try to get distinct record with regarding to tr_x from database then you can use GroupBy in entity framework.
So your code will be.
.GroupBy(x => x.tr_x).Select(x => x.First()).ToList();
Instead of
.Distinct().ToList();

How to create group clause in Entity Framework Core

I am trying to query 2 tables, Club and LinkClubUser. I want to retrieve the last club that a User is assigned from the last Date in the LinkclubUser.
I have the right SQL query:
select top 1
max(A.DataInscricao),
A.Nome, A.NomeNaCamisola, A.NumNaCamisola, A.Posicao, A.Situacao
from
Clube as A
inner join
LinkClubeUser as B on a.Id = b.IdClube
where
b.IdUser ='9faea9f3-28d7-4e34-8572-3102726d3c75'
group by
A.Nome, A.NomeNaCamisola, A.NumNaCamisola, A.Posicao, A.Situacao
I got the right row.
I try to convert this query to Entity Framework Core like this, but I get back more than 1 row:
var query = _dbContext
.LinkClubeUser
.Join(_dbContext.Clube,
lnk => lnk.IdClube,
clube => clube.Id,
(Lnk, clube) => new { Lnk, clube })
.Where(t => t.Lnk.IdUser == "9faea9f3-28d7-4e34-8572-3102726d3c75")
.GroupBy(t => new
{
t.clube.Id,
t.clube.Nome,
t.clube.NomeNaCamisola,
t.clube.NumNaCamisola,
t.clube.Posicao,
t.clube.Situacao,
t.clube.DataInscricao
}, t => t.clube)
.Select(g => new
{
Nome = g.Key.Nome,
NomeNaCamisola = g.Key.NomeNaCamisola,
NumNaCamisola = g.Key.NumNaCamisola,
Posicao = g.Key.Posicao,
Situacao = g.Key.Situacao,
DataInscricao = (DateTime)g.Max(p => p.DataInscricao)
}).Take(1);
but this code is converted by Entity Framework Core like this
SELECT
[lnk].[Id], [lnk].[Date], [lnk].[IdClub],
[lnk].[IdQuestionario], [lnk].[IdUser], [clube].[Id],
[clube].[ClubActual], [clube].[Date], [clube].[Nome],
[clube].[NomeNaCamisola], [clube].[NumNaCamisola], [clube].[Posicao],
[clube].[Situacao]
FROM
[LinkClubeUser] AS [lnk]
INNER JOIN
[Clube] AS [clube] ON [lnk].[IdClube] = [clube].[Id]
WHERE
[lnk].[IdUser] = N'9faea9f3-28d7-4e34-8572-3102726d3c75'
ORDER BY
[clube].[Id], [clube].[Nome], [clube].[NomeNaCamisola],
[clube].[NumNaCamisola], [clube].[Posicao], [clube].[Situacao],
[clube].[DataInscricao]
I don't see the group by clause.
What's wrong in my Entity Framework Core query?
I donĀ“t have the group clause.
I think you added all the clube table fields to your group clause so your group clause lost its nature and did not compile to SQL, while you added some of them in your first SQL query.
Edit
var query = (from user in _dbContext.LinkClubeUser
Join club in _dbContext.Clube on user.IdClub equals club.Id into cu
let clubUser = cu.DefaultIfEmpty() // outer join if you need it
Where clubUser.IdUser == "9faea9f3-28d7-4e34-8572-3102726d3c75")
Select new
{
Nome = user.Nome,
NomeNaCamisola = user.NomeNaCamisola,
NumNaCamisola = user.NumNaCamisola,
Posicao = user.Posicao,
Situacao = user.Situacao,
DataInscricao = (DateTime)clubUser.Max(p => p.DataInscricao)
}).Take(1);
Hope it helps.

Incorporate Enum.GetName(...) into Linq Query

I have the enumeration:
public enum CmdType {
[Display(Name = "abc")]
AbcEnumIdentifier = 0,
[Display(Name = "xyz")]
XyzEnumIdentifier = 1,
...
}
I'd like to get the names of each enumeration into my query, but even using .WithTranslations() I'm getting this error:
LINQ to Entities does not recognize the method 'System.String
GetName(System.Type, System.Object)' method, and this method cannot be
translated into a store expression.
The query:
var joinedRecord =
(
from m in mTable
join b in bTable on m.Id equals b.aRefId
select new {
aId = a.Id,
aAttrib1 = a.Attrib1
...
bCmdType = Enum.GetName(typeof(CmdType), b.CmdType)
}
).WithTranslations();
How do I return a generated value using Enum.GetName(...) within the query?
LINQ to entities tries to translate your query to SQL and it fails to do so, because there is no equivalent of the Enum.GetName method in SQL.
You need to materialize the results of the query and convert the enum values to their name in the memory.
var joinedRecords = (
from m in mTable
join b in bTable on m.Id equals b.aRefId
select new {
aId = a.Id,
aAttrib1 = a.Attrib1
...
bCmdType = b.CmdType
}
).AsEnumerable() //Executes the query, further you have simple CLR objects
.Select(o => new {
aId = o.Id,
aAttrib1 = o.Attrib1
...
bCmdTypeName = Enum.GetName(typeof(CmdType), o.CmdType)
});
You are calling Enum.GetName(typeof(CmdType), b.CmdType) which cannot be translated to SQL as the Enum definition is not in the DB if you take a look at your rows you'll see there is an int instead of the name of the Enum value in question.
Try this:
var joinedRecord =
(
from m in mTable
join b in bTable on m.Id equals b.aRefId
select new {
aId = a.Id,
aAttrib1 = a.Attrib1
...
bCmdType = b.CmdType
}
)
.AsEnumerable() // or ToList()
.Select( // map to another type calling Enum.GetName(typeof(CmdType), b.CmdType) )
.WithTranslations();
What this does is that by calling AsEnumerable() or ToList() you are no longer processing an instance of IQueryable<T> (which is what your original query returns, on the bad side once you do this all returned objects will be on memory). So once you have objects in memory you can use them just as any other C# object which should allow you to use the methods you want.
Try casting to AsEnumerable() so you can use LINQ to Objects. LINQ to Entities will try to translate it to SQL for which there is no equivalent:
var joinedRecord =
(from m in mTable
join b in bTable on m.Id equals b.aRefId)
.AsEnumerable()
.Select(x => new {
aId = a.Id,
aAttrib1 = a.Attrib1
...
bCmdType = Enum.GetName(typeof(CmdType), b.CmdType)
})
.WithTranslations();
See http://www.lavinski.me/ef-linq-as-emumerable/

select entity with one child in entity framework for oracle

Following query throws 'Oracle 10.2.0.3.0 does not support APPLY ' exception
var q = _dbTaxObjects
.Select(o => new TaxObjectItem()
{
MainAddress = o.MainAddress,
Id = o.Id,
ObjectName = o.ObjectName,
State = o.State,
LastCheck = o.Checks.OrderByDescending(ch => ch.EndDate).FirstOrDefault()
});
I need to select taxObjects with one child (taxObjectCheck) that has max endDate (if exists).
The query is working well if I comment LastCheck assignment.

Categories

Resources