Can't grasp how to join 2 tables in LINQ extension - entity-framework

I have 2 tables that I need to join with each other but I can't grasp how I can join them using a linq extension.
I can do it easy in SQL, but I'm struggling with linq.
My problem - 2 models:
public class GamesNight
{
[Key]
public int Id { get; set; }
public virtual ApplicationUser User { get; set; }
public string GamesNightTitle { get; set;}
public string GamesNightDescription { get; set; }
public string GamesNightLocation { get; set; }
public DateTime GamesNightDate { get; set; }
}
and an attendance model:
public class Attendance
{
public int Id { get; set; }
public virtual ApplicationUser User { get; set; }
public virtual GamesNight GamesNight { get; set; }
}
Pretty simple to grasp, the user 'attends' a 'gamesnight'.
I have a view model that reads
public class UpcomingGamesNightViewModel
{
public GamesNight GamesNight { get; set; }
public bool Attending { get; set; }
}
What I am trying to achieve is a built up array of UpcomingGamesNightViewModel where the GamesNight a gamesnight and attending is where the user is attending the games night via the attending table.
Thanking you!

Related

EF Core: How to organize models/tables and use DBQuery when I have 2 different tables relating to the same common one

Let's say I have a bike shops that sell various types of bikes: pro, kids, youth, leisure and any mixture. So I have a table of shops that refers/relates to a table of possible types. Now these shops also host events with the same types: events for pros, kids etc again any mixture. And so I have another table of events that also need to refer/relate to the same table of types:
I need to be able in a single quick query get a list of all bike types for a shop or event.
So I figured I'd have 3 main tables: Shops, Events, BikeTypes and two intermediate to link shops and events to bike types:
And I organized my models as:
public class BikeShop
{
public long Id { get; set; }
public string name { get; set; }
public string address { get; set; }
public string phone { get; set; }
}
public class BikeEvent
{
public long Id { get; set; }
public string name { get; set; }
public string description { get; set; }
public DateTime date { get; set; }
public string location { get; set; }
}
public class BikeType
{
public long Id { get; set; }
public string name { get; set; }
public string code { get; set; }
}
public class ShopBikeTypes
{
public long Id { get; set; }
public BikeShop shop { get; set; }
public BikeType biketype { get; set; }
}
public class EventBikeTypes
{
public long Id { get; set; }
public BikeEvent bikeevent { get; set; }
public BikeType biketype { get; set; }
}
With DataCotext:
public class DataContext : DbContext
{
public DbSet<BikeShop> Shops { get; set; }
public DbSet<BikeEvent> Events { get; set; }
public DbSet<BikeType> BikeTypes { get; set; }
public DbSet<ShopBikeTypes> ShopBikeTypes { get; set; }
public DbSet<EventBikeTypes> EventBikeTypes { get; set; }
}
Migration creates correct database structure just as my diagram. Great!
Now how do I make a straight forward query:
get list of all bike types for a shop
get list of all bike types for an event
Is my structure even correct?
Do I need some List<> in the main object models BikeShop and BikeEvent?
EF's include and theninclude seem to require some list?
This feels like such a typical scenario. What's the right way of doing this?
Thank you.
Those are the linq queries that you are asked but when i look at that your class models, i can say they are wrong. U need to define first which relation theyre having. if all of that relation has based on one-to-one, u wont gonna need any List<> in your class models. but if u have one-to-many relation,u gonna need them.
1- get list of all bike types for a shop
return DbContext.Shops
.Include(x>=x.ShopBikeTypes)
.ThenInclude(x=>x.BikeTypes).ToList();
2- get list of all bike types for an event
return DbContext.Events
.Include(x=>x.EventBikeTypes)
.ThenInclude(x=>x.BikeTypes).ToList();
3- Get all data in that relation
return DbContext.BikeTypes
.Include(x>=x.EventBikeTypes)
.ThenInclude(x=>x.Events).AsSplitQuery()
.Include(x=>x.ShopBikeTypes)
.ThenInclude(x>=x.Shops).AsSplitQuery()
.ToList();
it can be a tough query, do not try to use AsNoTracking() because it can cause Cartesian Explosion.
#BerkGarip: thank you for your help. I ended up with this models structure:
public class AShop
{
public long Id { get; set; }
public string name { get; set; }
public string address { get; set; }
public string phone { get; set; }
public List<AShopType> aTypes { get; set; }
}
public class AEvent
{
public long Id { get; set; }
public string name { get; set; }
public string description { get; set; }
public DateTime date { get; set; }
public string location { get; set; }
public List<AEventType> aTypes { get; set; }
}
public class AType
{
public long Id { get; set; }
public string name { get; set; }
public string code { get; set; }
}
public class AShopType
{
public long Id { get; set; }
public AType aType { get; set; }
}
public class AEventType
{
public long Id { get; set; }
public AType aType { get; set; }
}
In order to achieve what I needed using answer from #BerkGarip I figured out that the trick there was to have lists in the 'shop' and 'event' models to the intermediate objects which in turn have a single reference to 'type'. This way database layout is the same and it is many-to-many relationship and I can use 'include' and 'thenInclude' exactly as expected:
return await _context.AShops.Where(x => x.name == "Z")
.Include(x => x.aTypes)
.ThenInclude(y => y.aType)
.ToListAsync();

Load related entities with a single .Include() in Entity Framework?

Is there a better way to load all the related entities?
Below is the ScholarshipRequest class which also has Scholarship, Status, Student, Program and User.
public class ScholarshipRequest
{
public int Id { get; set; }
public int Year { get; set; }
public Status Status { get; set; }
public DateTime ApplicationDate { get; set; }
public DateTime ActionDate { get; set; }
public Scholarship Scholarship { get; set; }
public Program Program { get; set; }
public Student Student { get; set; }
public User User { get; set; }
}
I am just posting Scholarship class here, rest are similar.
public class Scholarship
{
public int Id { get; set; }
public string Name { get; set; }
}
The below code works fine but is there a better way where i can use a single .Include() to load them all or may be some other way?
ScholarshipRequestRepository repo = new ScholarshipRequestRepository(dBContext);
List<ScholarshipRequest> stdList = repo.Collection()
.Include("Status").Include("Student").Include("User").Include("Scholarship")
.Where(x => x.User.Id == userId).ToList();

Entity framework 7 relationships (friends of person and group of friends)

I'm playing and Learning EntityFramework 7 RC1.
I have
public class Person
{
public long PersonId{get;set;}
public ICollection<Relation> Friends {get;set;}
public ICollection<Group> Groups{get;set;} //Works if commented
}
public class Relation
{
public long RelationId { get; set; }
public long PersonId { get; set; }
public Person FriendWith { get; set; }
public ICollection<RelationType> Status { get; set; }
}
public class Group
{
public long GroupId { get; set; }
public long PersonId { get; set; }
public string Name { get; set; }
public ICollection<Person> Friends { get; set; }
}
Everything works in my model but not the last property of the Group class.
What i want is that a person can have Friends(Person) and can group his friends in groups (coworkers, friends...).
The top would be to have the possibility to query a Person and get :
- Person.Friends
- Person.Groups
- Person.Groups.FirstOrDefault().Friends
Thank you very for your help.

Map many to many objects using Entity Framework

For example we have profile and organisation. Both have articles.
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
}
public class Profile
{
public int Id { get; set; }
public string Email { get; set; }
public virtual ICollection<Article> Articles { get; set; }
}
public class Organisation
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Article> Articles { get; set; }
}
In this way Article should have two kinds of parent so it should have something like parent type to be able to access a parent when you select articles directly.
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
public int ParentId { get; set; }
public ArticleParentType Parent { get; set; }
}
Is it possible to map it using Entity Framework?
Is it a good idea to do it?
What is the best practice for storing this kind of data?
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
public int ParentId { get; set; }
public ArticleParentType Parent { get; set; }
}
Is it possible to map it using Entity Framework?
Is it a good idea to do it?
Possible yes but not a good idea. The underlying Database can't use a foreign key for Parentid. It would be slow.
What is the best practice for storing this kind of data?
A simple approach, with 2 Nullable parents and without CascadeOnDelete:
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
public virtual Profile Profile { get; set; }
public virtual Organisation Organisation { get; set; }
}
Alternatively you could use inheritance for Article, ie class OrganisationArticle : Article {}

entity framework code first - shared 1-to-many entity

I've been going around the block a couple of times on this, so I'm taking a fresh approach. I would like to figure out if it possible to have a single entity that is on the many-side of multiple 0-to-many relationships. This is what I'm trying to do:
A Client has 0-to-many Phones
public class Client
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ClientId { get; set; }
public string Name { get; set; }
public virtual ICollection<Phone> Phones { get; set; }
}
A Business has 0-to-many Phones
public class Business
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int BusinessId { get; set; }
public string Name { get; set; }
public virtual ICollection<Phone> Phones { get; set; }
}
And here is Phones:
public class Phone
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int PhoneId { get; set; }
public string Number { get; set; }
}
Of course, the problem with the Phones property in Business/Client is that this creates FK's in Phone to both Client and Business, which clutters-up Phones.
So, I saw another poster try creating a manual join table, but it seemed to be geared to the many-side participating in one relationship:
public class ClientPhone
{
public int ClientID { get; set; }
public int PhoneID { get; set; }
public virtual Client Client { get; set; } // One Client
public virtual Phone Phone { get; set; } // One Phone
}
Should I split Phone up into ClientPhones and BusinessPhones 'normal' entities using traditional 0-to-many relationships. If someone could give me some advice on the cleanest way to to model this, it would be very appreciated.
Thanks!
I think you can model this using table per hierarchy method ,
public class Client
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ClientId { get; set; }
public string Name { get; set; }
public virtual ICollection<ClientPhone> Phones { get; set; }
}
public class Business
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int BusinessId { get; set; }
public string Name { get; set; }
public virtual ICollection<BusinesPhone> Phones { get; set; }
}
public class Phone
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int PhoneId { get; set; }
public string Number { get; set; }
}
public class BusinesPhone:Phone
{
}
public class ClientPhone:Phone
{
}
This will create one table for both client and business phone with a discriminator column. Then you can easily separate client and business phones.