Many to Many relationship code first - asp.net-mvc

Hi I'm trying to create a database in MVC containing a list of Tv shows and Actors associated with them.
Each Tv show can have multiple Actors and an actor can appear on many tv shows. Each actor has a cast name too, for each show they appear in. Here's my models.
public class TvShow
{
public int ShowId { get; set; }
public string Name { get; set; }
public List<Actor> cast { get; set; }
}
public class Actor
{
public int ActorId { get; set; }
public string Name { get; set; }
public List<TvShow> shows { get; set; }
}
public class Cast
{
public int ShowId { get; set; }
public int ActorId { get; set; }
public string CastName { get; set; }
}
public class TvContext : DbContext
{
public DbSet<TvShow> Shows { get; set; }
public DbSet<Actor> Actors { get; set; }
}
I query the database and run the application to create the database for me, but the CastName attribute is not appearing in my linker table. Any help would be greatly appreciated.

How can EF know that you want to use entity Cast as a M:N relation table?
You have to link entity Cast from TvShow and Actor entities when you want to have there an additional property on many to many relationship. So the model can look like this:
public class TvShow
{
public int ShowId { get; set; }
public string Name { get; set; }
public List<Cast> Casts { get; set; }
}
public class Actor
{
public int ActorId { get; set; }
public string Name { get; set; }
public List<Cast> Shows { get; set; }
}
public class Cast
{
public string CastName { get; set; }
public TvShow TwShow { get; set; }
public Actor Actor { get; set; }
}
And you can get list of actors for given TvShow with following query:
twShow.Casts.Select(c => c.Actor);

Related

MVC implementation of many to many relationships

This is done using MVC .net framework and entity framework "database first" approach. There is a many to many relationship between two tables. They are connected through third table that has combined key as id from first table and id from second table.
public class ManyToManyTable
{
[Required]
[Key, Column(Order=0)]
public int firsttableid { get; set; }
[Required]
[Key, Column(Order=1)]
public int secondtableid { get; set; }
public int something { get; set; }
[ForeignKey("firsttableid")]
public virtual FirstTable firstTable { get; set; }
[ForeignKey("secondtableid")]
public virtual SecondTable secondTable { get; set; }
}
First and Second table have some id which is primary key.
I want to create View and Controller method that enables master detail entry form for this ManyToManyTable. that would have FirstTable in Master and SecondTAble in details, and all to be saved in ManyToManyTable when button Save is pressed.
Of course, both First and Second Table have this property:
public virtual ICollection<ManyToManyTable> ManyToManyTables { get; set; }
What is the easiest way to implement cases like this one?
Thank you!
EF has a default conventions for many-to-many relationships. No need to create specific
mapping class. You have to include navigation properties in both "FirstTable" and "SecondTable" Class as shown below.
public class FirstTable
{
public FirstTable()
{
secondTableProperties = new HashSet<SecondTable>();
}
public int Id { get; set; }
public int MyProperty2 { get; set; }
public int MyProperty3 { get; set; }
public virtual ICollection<SecondTable> secondTableProperties { get; set; }
}
public class SecondTable
{
public SecondTable()
{
FirstTableProperties = new HashSet<FirstTable>();
}
public int Id { get; set; }
public int MyProperty2 { get; set; }
public int MyProperty3 { get; set; }
public virtual ICollection<FirstTable> FirstTableProperties { get; set; }
}
Remove mapping class from DBContext , only include above two classes. Build and run the application , EF will automatically create a Mapping table in SQL server. Usually the Mapping table contains only the primary keys of other two tables.
You can use Fluent API to take some control on the created mapping table
modelBuilder.Entity<FirstTable>()
.HasMany<SecondTable>(s => s.FirstTableProperties)
.WithMany(c => c.secondTableProperties)
.Map(cs =>
{
cs.MapLeftKey("FirstTableId");
cs.MapRightKey("SecondTableId");
cs.ToTable("ManyToManyTable");
});
If you want to work with a join table with additional properties, above mentioned many-to-many relationship won't work . In that case you will have to create two one-to-many relationships as shown below.
public class FirstTable
{
public int Id { get; set; }
public int MyProperty2 { get; set; }
public virtual ICollection<ManyToManyTable> manytomany { get; set; }
}
public class SecondTable
{
public int Id { get; set; }
public int MyProperty2 { get; set; }
public virtual ICollection<ManyToManyTable> manytomany { get; set; }
}
public ManyToManyTable
{
[Required]
[Key, Column(Order=0)]
public int firsttableid { get; set; }
[Required]
[Key, Column(Order=1)]
public int secondtableid { get; set; }
public int AdditionalProperty { get; set; }
public virtual FirstTable first { get; set; }
public virtual SecondTable Second { get; set; }
}

How to include a child object's child object in Entity Framework 5 Not working

I saw this How to include a child object's child object in Entity Framework 5
However, I'm using MVC 5 and that doesn't seem to be working.
I have a typical Tournament, Games, Teams structure, and am trying to include Teams when I query the tournament.
I am trying to run
db.Tournaments.Include(t => t.Games.Select(g => g.Team1)).ToList();
However Team1 is coming back null. Here are my classes:
public class Tournament
{
public int TournamentId { get; set; }
public string Name { get; set; }
public virtual List<Game> Games { get; set; }
public virtual List<Standing> Standings { get; set; }
}
public class Game
{
public int GameId { get; set; }
public Location Location { get; set; }
public int LocationId { get; set; }
public virtual Team Team1 { get; set; }
public int Team1Id { get; set; }
public virtual Team Team2 { get; set; }
public int Team2Id { get; set; }
public int Team1Score { get; set; }
public int Team2Score { get; set; }
public DateTime Time { get; set; }
public Tournament Tournament { get; set; }
public int TournamentId { get; set; }
}
public class Team
{
public int TeamId { get; set; }
public string Name { get; set; }
public string Coach { get; set; }
}
Does anyone have any suggestions?
You are trying to load a single cell from the Games table in the Db, I don't think you can do this the way you are trying too.
You have your Navigation properties set to Virtual, so you should lazy load automatically when you call the property that you need. There is no need for an include statement.
All you normally need to do is iterate through the list of games in tournaments
var Tournaments = Db.Tournaments.ToList();
foreach (var game in Tournaments.Games)
{
game.Team1.TeamId;
game.Team1.Coach;
game.Team1.Name;
}
db.Tournaments.Include(t => t.Games.Team1).ToList();
This is the correct way of Including single child entities in EF5.

Entity framework migration of Collections

I have a model that looks like this
public abstract class Item
{
public int ItemId { get; set; }
public String Title { get; set; }
public String Description { get; set; }
public DateTime PurchaseDate { get; set; }
public ICollection<String> Pictures { get; set; }
public Int32 MinimumPrice { get; set; }
public DateTime Deadline { get; set; }
public Boolean VisibleBids { get; set; }
public Boolean Handled { get; set; }
public DateTime PlacementDate { get; set; }
public ApplicationUser User { get; set; }
}
In my controller I do
db.Items.ToList()
This leaves the Pictures field for all fetched objects null because its how the entity framework works. What is a good solution to fetch them in one query?
I hope you already done with Navigation properties between your tables, Now you just need to make your collection virtual and use the concept of eager loading when you need data from both the tables
public virtual ICollection<String> Pictures { get; set; }
and use include in linq like
db.Items.Include("Pictures").ToList()
So here by making virtual navigation you are saying that only take the data of related entity when you needed and whenever you need the data use the Include for eager loading.
For setting navigation properties please have a look on the code.
Suppose the scenario where we have a Post and on this we have multiple comments like
class Posts
{
public int PostsId { get; set; }
public string PostsDescription { get; set; }
public virtual ICollection<Comments> Comments { get; set; }
}
class Comments
{
public int CommentsId { get; set; }
public string CommentsDescription { get; set; }
public int PostsId { get; set; }
public virtual Posts Posts { get; set; }
}

CypherTypeException: Properties containing arrays of non-primitive types are not supported

I am getting this exception while creating nodes in NEO4J 2.0.3 using C# Client for NEO4J.
My Node Structure is like this
namespace UserGraph.BusinessObjects
{
public class UserInfo
{
public int UserID { get; set; }
public string UserName { get; set; }
public int HeadendId { get; set; }
public int Score { get; set; }
public string ThirdPartyObjID { get; set; }
public long ThirdPartyTypeId { get; set; }
public string[] ThirdPartyFriendsIds { get; set; }
public List<Programme> Programs { get; set; }
public List<Channel> Channels { get; set; }
}
public class Channel
{
public long ChannelID { get; set; }
public String ChannelName { get; set; }
}
public class Programme
{
public long ProgrammeID { get; set; }
public String ProgrammeName { get; set; }
}
}
I think Neo4j nodes don't hold Complex data. I searched and found on this link http://docs.neo4j.org/chunked/stable/graphdb-neo4j-properties.html
Can any one tell me is there any way by which i can store the list of channel and program objects in my UserInfo class.
I am running into the same issue and I am not sure I agree with the concept that all complex "properties" should be relationships. At the end of the day, the entire "node" should be something that can be serialized and stored -- this is one of the advantages of using JSON to serialize/deserialize the node. Coder the following
public class Address {
public string Line1 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Country { get; set; }
}
public class User {
public string Name { get; set; }
public string email { get; set; }
public Address HomeAddress { get; set; }
public Address WorkAddress { get; set; }
}
While create nodes for Addresses can be done, I would ask the question -- why should the developer be forced to create nodes and relationships for something like this. If I never intend to do any direct queries on the properties of the Address class independently of the main user, then it is far simpler to treat the entire user as a complex object and store it in its entirety as the data for the node in the graph.

Circular reference with ManyToMany relationship and automapper

Given the following Domain Entities:
public class Person {
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual ISet<PersonClub> Clubs { get; set; }
public Person() {
this.Clubs = new HashSet<PersonClub>();
}
}
public class Club {
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual ISet<PersonClub> Members { get; set; }
public Club() {
this.Persons = new HashSet<PersonClub>();
}
}
public class PersonClub {
public virtual Guid Id { get; set; }
public virtual Person Person { get; set; }
public virtual Club Club { get; set; }
}
and DTO's:
public class PersonDTO {
public Guid Id { get; set; }
public string Name { get; set; }
public ISet<ClubDTO> Clubs { get; set; }
public PersonDTO() {
this.Clubs = new HashSet<ClubDTO>();
}
}
public class ClubDTO {
public Guid Id { get; set; }
public string Name { get; set; }
public ISet<PersonDTO> Members { get; set; }
public ClubDTO() {
this.Members = new HashSet<PersonDTO>();
}
}
Is there a way to map these Domain Entities to their DTO's? The problem is that PersonDTO needs a collection of ClubDTO, not just Club, and vice versa for ClubDTO needing a collection of PersonDTO and not just Person.
This design causes an infinite loop when trying to map PersonClub -> PersonDTO and PersonClub -> ClubDTO:
Mapper.CreateMap<Person, PersonDTO>();
Mapper.CreateMap<Club, ClubDTO>();
Mapper.CreateMap<PersonClub, ClubDTO>()
.ConvertUsing(x => Mapper.Map<Club, ClubDTO>(x.Club));
Mapper.CreateMap<PersonClub, PersonDTO>()
.ConvertUsing(x => Mapper.Map<Person, PersonDTO>(x.Person));
I understand why this is happening, but am curious to how others handle this situation.
In this situation when calling Mapper.Map<Person, PersonDTO>(personEntity), it isn't necessary to load all members of all clubs that a person is a part of (The relationship doesn't need to go that deep ever). Same is true for Mapper.Map<Club, ClubDTO>(clubEntity).
Is this a design flaw? Would it be better to not have a PersonClub domain entity and just have public virtual ISet<Club> Clubs { get; set; } as the ManyToMany relationship? Although I believe this would still cause the circular reference.
Any input is appreciated.

Resources