Child List Element Gets Only 1 Record in Entity Framework - entity-framework

In Entity Framework, I would like to get one object which includes a list, but list gets only first record.
I have 2 objects Sale and Profile, they are different from database objects, I create these objects in query like "select new Sale { }". Profile object contains Sale type list. When query executed, list gets just first record in database.
Sale Complex Object
public class Sale
{
public int Id { get; set; }
public string Header { get; set; }
public double Price { get; set; }
}
Profile Complex Object
public class Profile
{
public int Id { get; set; }
public string Name { get; set; }
public List<Sale> SalesList { get; set; }
}
I use left join because it should insert this object to list, if next object is null.
Query Here
Profile profile = (from u in db.USER
join s in db.SALE on u.ID equals s.USER_ID into saleleft
from salej in saleleft.DefaultIfEmpty()
where u.ID == _userId
select new Profile
{
Id = u.ID,
Name = u.NAME,
SalesList= new List<Sale>()
{
salej != null ? new Sale
{
Id=postj.ID,
Header=salej.HEADER,
Price=salej.PRICE
} : null
}.ToList()
}).FirstOrDefault();
I guess this can be about FirstOrDefault() method. Hence I think it should get all records to SalesList. How can I get all records to list? Any idea?
Thanks in advance.

I think you need to use group here. Could you try this and let me know if it works?
// didn't test the code
Profile profile = (from u in db.USER
join s in db.SALE on u.ID equals s.USER_ID into saleleft
where u.ID == _userId
from salej in saleleft.DefaultIfEmpty()
group salej by new { u.ID, u.NAME } into g
select new Profile
{
Id = g.Key.ID,
Name = g.Key.NAME,
SalesList = g.Select( x => new Sale { Id = postj.ID, Header = x.HEADER, Price = x.PRICE }).ToList()
}).FirstOrDefault();
Btw, what is postj?

Related

.NET Core - join 2 tables with AsQueryable

I have two nested classes: Partner contains a Company (that has a field "Name")
I do a search by Id on the partner's Id
I want to do a search on the company's "Name" field
here is my poco:
public class Partner
{
[Required]
public int? Id { get; set; }
[Required]
public Company Company { get; set; }
using AsQueryable, I can then stack filters one by one
I try to have a query that joins the second table to do a search on that entity's name field
public DbSet<Partner> Partners { get; set; }
...
var data = _context.Partners.AsQueryable();
if (partnersSearch.SearchById != null)
{
data = data.Where(p => p.Id == partnersSearch.SearchById.GetValueOrDefault());
}
if (partnersSearch.SearchByName != null)
{
data = data.Include(a => a.Company.Select(b => b.Name = partnersSearch.SearchByName));
but for the join between the tables, the last line cannot compile
it complains that Company does not contain a definition of has no Select
what am I doing wrong ?
thanks for helping me on this
If you try a where after your include. Does that help?
data.Include(a => a.Company).Where(partner=>partner.Company.Name.equals(partnersSearch.SearchByName))

Include with additional param on join

I have many Nations and for each Nation i have a lot of Teams.
The GetTeam endpoint in team controller retrieve a single Team and its related Nation. Via LINQ the query is this:
Context.Teams.Include(t => t.Nation).First(t => t.Id.Equals(__id))
The resulting JSON is what I want:
{"team":{"name":"Team1","nation":{"id":1,"name":"Nation1"}}
Let's say now that the property "name", both in Team and Nation model is dropped and a new model relation is created, with Translation.
What I want now is to retrieve the same JSON, but with a different query based on culture.
Gettin crazy understand how I can achieve it with include.
How can I compose this query in LINQ ?
select *
from Teams inner join
Translations TeamTr on Teams.id = TeamTr .id and TeamTr .culture = "IT" inner join
Nations on Teams.nation_id = Nations.id inner join
Translations NationTr on Nations .id = NationTr .id and NationTr .culture = "IT"
And compose the resulting data as JSON above?
for example:
(from team in Context.Teams
join teamTr in Context.Translations on team.id equals teamTr.id
join nation in Context.Nations on team.nation_id equals nations.id
join nationTr in Context.Translations on nation.id equals nationTr.id
where teamTr.culture == "IT" && nationTr.culture == "IT"
select new
{
teamName = team.name,
nationName = nation.name
}).ToList();
Nice catch tdayi.
First of all I've created a new class, that will be the container of the linq result:
public class TeamDetailLinqDto
{
public Team Team { get; set; }
public Translation TeamTranslation { get; set; }
public Nation Nation { get; set; }
public Translation NationTranslation { get; set; }
}
and this is the linq query:
public IQueryable<TeamDetailLinqDto> GetTeams()
{
var result = from team in Context.Teams
join teamTranslation in Context.Translations on
new { Id = team.Id, Locale = "IT" }
equals new { Id = teamTranslation.EntityId, Locale = teamTranslation.Locale }
join nation in Context.Nations on team.NationId equals nation.Id
join nationTranslation in Context.Translations on
new { Id = nation.Id, Locale = "IT" }
equals new { Id = nationTranslation.EntityId, Locale = nationTranslation.Locale }
select new TeamDetailLinqDto
{
Team = team,
TeamTranslation = teamTranslation,
Nation = nation,
NationTranslation = nationTranslation
};
return result;
}

Self referencing (1:1) a table in Entity Framework code first model

I'm trying to self reference a table in my model to get a couple of details for my User entity
I have a class that looks like:
public class User
{
[Key]
[Column("recid")]
public int Id { get; set; }
[Column("givenname")]
public string FirstName { get; set; }
[Column("sn")]
public string LastName { get; set; }
[Column("mail")]
public string Email { get; set; }
[Column("managerEmail")]
public string LineManagerEmail { get; set; }
public string LineManagerFirstName { get; set; }
public string LineManagerLastName { get; set; }
}
How can I map this so that when returning a User the LineManagerFirstName and LineManagerLastName is retrieved from the same table, joined on LineManagerEmail?
for example, I anticipate the SQL to be something like:
SELECT
user.recid,
user.givenName,
user.sn,
user.mail,
user.managerEmail,
manager.givenName as lineManagerFirstName,
manager.givenName as lineManagerLastName,
FROM user
INNER JOIN user AS manager
ON user.managerEmail = manager.mail
In my Context class, I know I'll need to override the OnModelCreating method:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<User>().
}
...but being new to EF, this is where I'm getting a bit stuck!
If you use a view, you will probably not be able to update users as a view is readonly.
You should create entities according to tables and then query according to your needs and materialize a UserExtended with a query like
var q = from
u in Users
select
new UserExtended {
Id = u.Id,
/* .... */
LineManagerFirstName = u.Manager.FirstName
/* .... */
}
or a more elaborated query, in case of self join without the PK.
var q =
from u in Users
join m in Users on u.Email equals m.Email
select
new UserExtended {
Id = u.Id,
/* .... */
LineManagerFirstName = m.FirstName
/* .... */
}
will give you the following SQL (fields name do not match as I use one of my schema)
SELECT
[Extent1].[idUtilisateur] AS [idUtilisateur],
[Extent2].[Email] AS [Email]
FROM [dbo].[tableU] AS [Extent1]
INNER JOIN [dbo].[tableU] AS [Extent2] ON
([Extent1].[Email] = [Extent2].[Email])
OR (([Extent1].[Email] IS NULL) AND ([Extent2].[Email] IS NULL))

IQueryable.Select to a List type sub POCO

I have an Entity Framework model in which there is a "Customers" and a "CustomerPhones" table. A customer can have multiple phone numbers so the "Customer" entity has a collection of "Phone". I can query the model with no problem :
using (CustomerEntities context = new CustomerEntities())
{
Customer customer = context.Customers.FirstOrDefault();
CustomerPhone phone = customer.Phones.FirstOrDefault();
MessageBox.Show(customer.Name + " " + phone.Number);
}
The model is too complex for what I need to do (even though my example is basic) so I'm trying to boil it down to simpler POCOs. Here are the 2 simple classes :
public class SimplePhone
{
public int Id { get; set; }
public string Number { get; set; }
}
public class SimpleCustomer
{
public int Id { get; set; }
public string Name { get; set; }
//Phones is a list because a single Customer can have multiple phone numbers
public List<SimplePhone> Phones { get; set; }
}
I can populate the simple properties of the object using the "Select" method of "IQueryable" :
using (CustomerEntities context = new CustomerEntities())
{
IQueryable<SimpleCustomer> customers = context.Customers.Select(
c => new SimpleCustomer
{
Id = c.Id,
Name = c.Name
}
);
SimpleCustomer customer = customers.FirstOrDefault();
MessageBox.Show(customer.Name);
}
So my question is pretty simple : how can I populate the "Phones" property which is a list?
using (CustomerEntities context = new CustomerEntities())
{
IQueryable<SimpleCustomer> customers = context.Customers.Select(
c => new SimpleCustomer
{
Id = c.Id,
Name = c.Name
Phones = ///????
}
);
SimpleCustomer customer = customers.FirstOrDefault();
SimplePhone phone = customer.Phones.FirstOrDefault();
MessageBox.Show(customer.Name + " " + phone.Number);
}
Let me know if I'm unclear and/or you need more details.
Thanks!
I'm not sure if there isn't something more to your question, but as far as I understand, you can just call ToList and it will be materialized as a list:
IQueryable<SimpleCustomer> customers =
context.Customers.Select(c => new SimpleCustomer
{
Id = c.Id,
Name = c.Name,
Phones = c.Phones.Select(p => new SimplePhone
{
Id = p.Id, // Unless you want the custom Id, i.e. c.Id
Number = p.Number
}).ToList();
});

How to perform a left outer join using Entity Framework using navigation properties

I'm trying to find out how I would define the code first navigation properties on these two classes to perform something similiar to this query:
SELECT USERID, FIRSTNAME, LASTNAME, COURSEID, NAME
FROM User
LEFT OUTER JOIN Course ON User.USERID = Course.USERID
WHERE COURSEID = 1
So I'm trying to find a list of users together with if they have attended a certain course.
public class User
{
public int UserId {get;set; }
public string FirstName {get;set;}
public string LastName {get;set;}
public virtual ICollection<Course> Courses { get; set; }
}
public class Course
{
public int CourseId { get;set; }
public int UserId { get;set; }
public string Name { get;set; }
public virtual User User {get;set;}
}
If I was to write a query to achieve this
var u = Users.Where(x => x.Courses.Any(x => x.CourseId = 1));
This does a subquery, which is not what I wanted (as people who didnt attend the course would not show).
How would the navigation property be defined?
HasMany(t => t.Courses).WithOptional(t => t.User).HasForeignKey(t => t.UserId);
Check this link:
http://msdn.microsoft.com/en-us/library/vstudio/bb397895.aspx
Left outer joins in LINQ are done via DefaultIfEmpty method.
var u = Users.Select ( x => new {
User = x,
AttendedCourse = x.Courses.Any()
} );
For specific course id,
var u = Users.Select ( x => new {
User = x,
AttendedCourse = x.Courses.Any( c => c.CourseID == 1 )
} );
Sub query is the only way to write related queries, However, EF will choose the best suitable join type and will give you correct results. And EF can manage mostly all kinds of queries without doing joins.