I have two tables
People Relation
------------- -----------------
Id (int) Id (int)
Name (string) ParentPeopleId (int)
ChildPeopleId (int)
I need to get all people by Relation table with union all.
The relation table has two foreign keys. And there is one problem with mapping them. The mapping is one to many. People has many Relation, Relation has one People.
I mapped them like this:
HasRequired(r=> r.People).WithMany(p=>p.Relation).HasForeignKey(r=>r.ChildPeopleId);
So, how can I map the second foreign key?
Per each FK column in your Relations table you should have a navigation property in your Relation entity (this is not mandatory, but what is mandatory is have at least one navigation property between the entities involve in the relationship). In this case you have two relationships between People and Relations, and a navigation property represents one end in an relationship. Your model could be this way:
public class Relation
{
public int Id {get;set;}
public int ParentPeopleId {get;set;}
public int ChildPeopleId {get;set;}
public virtual People ParentPeople {get;set;}
public virtual People ChildPeople {get;set;}
}
public class People
{
public int Id {get;set;}
public string Name {get;set;}
public virtual ICollection<Relation> ParentRelations {get;set;}
public virtual ICollection<Relation> ChildRelations {get;set;}
}
And the Fluent Api configurations like this:
HasRequired(r=> r.ParentPeople ).WithMany(p=>p.ParentRelations ).HasForeignKey(r=>r.ParentPeopleId);
HasRequired(r=> r.ChildPeople).WithMany(p=>p.ChildRelations ).HasForeignKey(r=>r.ChildPeopleId );
Now if you don't want to work with one of the collection navigation properties in your People entity, you can create an unidirectional relationship. For example if you don't want ParenRelations navigation property, you can configure that relationship as follow:
HasRequired(r=> r.ParentPeople).WithMany().HasForeignKey(r=>r.ParentPeopleId);
Update
Let me start first with a suggestion. I thing your table Relation is not playing any role is you have only those columns. If a person con only have a parent I would change your model to the following:
public class People
{
public int Id {get;set;}
public string Name {get;set;}
public int ParentId {get;set;}
public virtual People Parent {get;set;}
public virtual ICollection<People> Children {get;set;}
}
And you relationship configuration would be:
HasOptional(r=> r.Parent).WithMany(p=>p.Children).HasForeignKey(r=>r.ParentId);
Now going back to your current model, EF sees your ChildPeopleId property as an simple scalar column, it doesn't know it's a FK column, that's way I suggested above map two relationship instead one.
Another thing, with the below line
var Peoplelist = MyDbContext.People.Include(p=>p.Relations.Select(r=>r.People)).ToList();
You are telling to EF that you want to load the Relation entities related to a People, but also you want to load the People related with each Relation, which is at the same time the same People where the Relation came from, so, you don't need to do the last select, if your data is properly related, that People navigation property is going to be loaded when you execute your query,so, that query should be this way:
var Peoplelist = MyDbContext.People.Include(p=>p.Relations).ToList();
Related
I have the following models
public class Student
{
public int Id {get; set; }
public string Name {get; set; }
public ICollection<StudentToCourse> StudentToCourse {get; set; }
}
public class StudentToCourse
{
public int StudentId{get; set; }
public Student Student {get; set; }
public int CourseId{get; set; }
public Course Course {get; set; }
}
public class Course
{
public int Id {get; set; }
public string Name {get; set; }
public ICollection<StudentToCourse> StudentToCourse {get; set; }
}
I want to get a list of all COURSE per student ID, how do I go about doing that?
Short answer: SELECT and match on the Id values. Or programatically -
foreach(Student s in yourstudentList)
{
foreach(StudentToCourse stc in s.StudentToCourse)
{
if(stc.StudentId = s.Id)
//this is one you want, do something with it
}
}
Better answer:
First let's look at your model...
Imagine the underlying database structure.
Your middle table is known as a lookup.
You don't really need the entire Student, nor the entire Course object in it.
Also, your Course object does not need to know about either of the other objects.
If you can imagine three tables in your database you can see how you would logically connect a Student to a Course across the three tables.
Your model is still incomplete though. Within your application you still need a container, in this case a List courseIds. In this way your Student doesn't need to care about all the entries in the Student/Course lookup table, just the ones applicable to the particular Student. And you have an easily accessible object to pull data from, or send updates to, the database.
On initial population of the courseIds collection you would do a
SELECT FROM StudentToCourse where StudentId = x
You can then JOIN on your Course table to pull values such as the Course name.
If you find you need to do a lot of those look ups you may cache your Course list and lower your database traffic at the cost of some ram.
Each time you make a new student you would want to populate their list of course Ids and when committing the student to the database you would save your look up table.
This keeps your objects as lightweight as possible while maintaining their relationships.
There are various ways to write the SELECT statement in your dev environment, search them out and find one you like (or that matches your company's current practices) and get used to consistently using the same one. It will keep your code more readable and manageable.
How would I add a foreign key linking my Club class and my ClubEvent class together in a one-to-many relationship where Club is the parent class and ClubEvent is the child.
These are the models I am using
public class Club
{
// Class to manage a single Club
[Key]
public int ClubID { get; set;
}//end Club
public class ClubEvent
{
[Key]
public int EventID { get; set; }
}
I want to connect these two tables so I can add events for a club so I can display only the relevant events for each club
This is pretty basic MVC, and if you need help with this stuff in the future please complete this tutorial: http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net-mvc-application it is great!
Since ClubEvent is a 'child' of Club (meaning one club can have one or many events) you want to have the reference to the parent in the child. So, you will add a reference to clubEvent linking each instance of that object to the appropriate club. Add this to your ClubEvent Object..
public int ClubID {get; set;}
[ForeignKey("ClubID")]
public virtual Club Club {get;set;}
By adding the navigation property (virtual Club Club) you will be able to make a call to the parent object from the ClubEvent child. (club)this.ClubEvent.
displaying this is easily achieved by querying the ClubEvents table with the parent Club ID. Like:
var events = db.ClubEvents.Where(e => e.ClubID == id)
Where 'id' is the ClubID passed to the method in your controller.
Hope this helps, if you have any issues check this link out because it has great examples for every relation type in MVC.
http://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-a-more-complex-data-model-for-an-asp-net-mvc-application
I am developing an app where i am using MVC in Presentation layer so I have to define model classes in it.....and because of that I want relationship in that models.
How can we define relationship in model without Dbcontext class file.
I don't exactly understand what you are asking for, but I will take a shot.
EF creates relationships in models by having a reference to the related model(s).
Say you have models Cart and Item. A Cart can contain many Items, and any one Item can only belong to one Cart. This would be a one-to-many relationship.
public class Cart
{
public int CartId {get;set;}
//other properties
public List<Item> Items {get;set;}
}
public class Item
{
public int ItemId {get;set;}
// other properties
public Cart Cart {get;set;}
}
So from your Cart class you can fetch any Items it contains, and from any of those Items you can get the Cart that contains them.
Again, not sure if this is what you are asking for, and this is very quickly thrown together, but hopefully it helps.
I have an entity/class/table which is referenced from several other entities, and I use Fluent NHibernate to handle the ORM for me. In a few instances, it's a simple reference where I can store the foreign key ID as a column and handle the reference in that simple way, but in a few other instances I need to reference a list of these items, and it needs done for at least three classes I can think of. You can assume this setup will be copied to handle the other classes' relationships.
Here's how the common entity looks (the one that is owned by several other entities in HasManys):
public class Student {
public virtual int Id {get; set;}
public virtual string Name {get; set;}
}
And, here's what the ShopCourse entity looks like:
public class ShopCourse {
public virtual int Id {get; set;}
public virtual int Name {get; set;}
public virtual IList<Student> Students {get; set;}
}
Imagine that a couple other classes I have, such as specific courses, can "own" several students. In order to maintain that relationship I must create a table in my database that tracks the foreign keys between the two (for each entity that references Student) - no entity needed for this intermediate table, and Fluent won't need to think of it unless I hand it the string name of the table itself:
Table: ShopCourseStudents
int - ShopCourseId
int - StudentId
Lastly, here are my mappings. You can assume that the entities themselves map out fine - things such as the naming scheme for the Id are resolved and working correctly. The issue lies when I attempt to initialize any entity that has a HasMany of Student:
//Inside a FluentlyConfigure().Mappings(m => m.AutoMappings.Add() call:
.Override<ShopCourse>(map => {
map.HasMany(x => x.Students)
.Table("ShopCourseStudents")
.KeyColumns.Add("ShopCourseId")
.KeyColumns.Add("StudentId")
.Cascade.All();
})
The issue is that when I attempt to load a list of ShopCourses I get the Fluent error:
Foreign key (ABC123AF9:Student [ShopCourseId, StudentId]) must have
same number of columns as the referenced primary key (ShopCourses
[Id])
I do not override Fluent's mapping of Student as it's straightforward. For the purpose of this example, Student doesn't need to know which ShopCourses it belongs to, or any of the other courses that may own that particular Student record.
This seems like I'm doing something basic, wrong - what is it, exactly? Much obliged in advance!
So, the issue was with the custom code that I re-use with my projects, apparently the piece written to handle the ManyToMany convention is mostly broken. What I was looking for here was a ManyToMany relationship, not HasMany. The issue I had was that my code was forcing a reference on the child object (in this example, Student) to the parent, which I do not need and only complicates things. Removing that, and my ManyToMany then works:
.Override<ShopCourse>(map => {
map.HasManyToMany(x => x.Students)
.Table("ShopCourseStudents")
.ParentKeyColumn("ShopCourseId")
.ChildKeyColumn("StudentId")
.Cascade.All()
In this question I am looking for links/code to handle an IList<OrderLine> in an MVC 2 edit form. Specifically I am interested in sending a complete order to the client, then posting the edited order back to an object (to persist) using:
Html.EditorFor(m => m.orderlines[i]) (where orderlines is an enumerable object)
Editing an Order that has multiple order lines (two tables, Order and OrderLine, one to many) is apparently difficult. Is there any links/examples/patterns out there to advise how to create this form that edits an entity and related entities in a single form (in C# MVC 2)?
The IList is really throwing me for a loop. Should I have it there (while still having one form to edit one order)? How could you use the server side factory to create a blank OrderLine in the form while not posting the entire form back to the server? I am hoping we don't treat the individual order lines with individual save buttons, deletes, etc. (for example, they may open an order, delete all the lines, then click cancel, which shouldn't have altered the order itself in either the repository nor the database.
Example classes:
public class ViewModel {
public Order order {get;set;} // Only one order
}
public class Order {
public int ID {get;set;} // Order Identity
public string name {get;set;}
public IList<OrderLine> orderlines {get;set;} // Order has multiple lines
}
public class OrderLine {
public int orderID {get;set;} // references Order ID above
public int orderLineID {get;set;} // Order Line identity (need?)
public Product refProduct {get;set;} // Product value object
public int quantity {get;set;} // How many we want
public double price {get;set;} // Current sale price
}
You need to understand List<>/Array/IEnumerable model binding:
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
http://blog.stevensanderson.com/2010/01/28/editing-a-variable-length-list-aspnet-mvc-2-style/
http://www.hanselman.com/blog/ASPNETWireFormatForModelBindingToArraysListsCollectionsDictionaries.aspx