Below are two tables that has a many to many relation and and also another table that has a relation with the two first. A mapping table is created by Visual Studio with the name OrderEmployee, but when I run the application and enter some information to the Timeunit create form, the mapping table OrderEmployee is empty!
Should there not be some IDs added to that table since it has a relation with the Timeunit table or how is this mapping table thing working, when will there be data added to the mapping table? Or is something wrong with my Entity Classes?
public class Order
{
public int ID { get; set; }
public string Name { get; set; }
public int? ManufacturerID { get; set; }
public virtual Manufacturer Manufacturer { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
public class Employee
{
public int ID { get; set; }
public string Name { get; set; }
public int EmployeeNumber { get; set; }
public virtual ICollection<Timeunit> Timeunits { get; set; }
public virtual ICollection<Order> Order { get; set; }
}
public class Timeunit
{
public int ID { get; set; }
public int Week { get; set; }
public int HoursPerWeek { get; set; }
public int EmployeeID { get; set; }
public int? OrderID { get; set; }
public virtual Employee Employee { get; set; }
public virtual Order Order { get; set; }
}
EDIT:
Create Method for Timeunit:
public ActionResult Create([Bind(Include = "ID,Week,HoursPerWeek,EmployeeID,OrderID")] Timeunit timeunit)
{
if (ModelState.IsValid)
{
db.Timeunits.Add(timeunit);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.ProjectID = new SelectList(db.Orders, "ID", "Name", timeunit.OrderID);
ViewBag.ResourceID = new SelectList(db.Employees, "ID", "Name", timeunit.EmployeeID);
return View(timeunit);
}
Related
My Entities:
public partial class Student: IBrand
{
public Student()
{
Grades = new HashSet<Grade>();
}
[Key]
public int StudentId { get; set; }
[ForeignKey("Users")]
public string UserId { get; set; }
public ApplicationUser User { get; set; }
[ForeignKey("Parent")]
public int? ParentId { get; set; }
public Parent Parent { get; set; }
public int? SectionId { get; set; }
public string FatherName { get; set; }
public int classNumber { get; set; }
public Section Section { get; set; }
public string brevetResult { get; set; }
public DateTime? dateLeftAec { get; set; }
public string additionalInfo { get; set; }
public bool bacc { get; set; }
public string baccResult { get; set; }
public string baccSection { get; set; }
public int BrandId { get; set; }
[JsonIgnore]
public Brand Brand { get; set; }
public virtual ICollection<StudentRegistration> StudentReg { get; set; }
public virtual ICollection<Grade> Grades { get; set; }
public virtual ICollection<Absence> Absences { get; set; }
public virtual ICollection<StudentStudyYear> StudentStudyYears { get; set; }
}
public class Grade: IBrand
{
public int gradeId { get; set; }
public int grade { get; set; }
public int StudentId { get; set; }
public int SubjectId { get; set; }
public int TeacherId { get; set; }
public int TermId { get; set; }
public int SectionId { get; set; }
public bool IsApproved { get; set; }
public string ResultToEdit { get; set; }
public bool IsEditedByAdmin { get; set; }
public virtual Student Student { get; set; }
public virtual Subject Subject { get; set; }
public virtual Teacher Teacher { get; set; }
public virtual Term Term { get; set; }
public virtual Section Section { get; set; }
public int BrandId { get; set; }
[JsonIgnore]
public Brand Brand { get; set; }
public virtual ICollection<GradeStudyYear> GradeStudyYears { get; set; }
}
I'm trying to get a student with his grades, but I encountered a problem with circular references. I tried to add this to the startup file:
services.AddMvc().AddJsonOptions(options =>
{
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
});
That seemed to solve the circular references problem, but then I started getting 5GB worth of data... so that code apparently just suppressed the error without solving the circular data problem.
I tried to put the attribute [JSONIgnore] in my grade.cs file, but I need to get a student from grade so it will not be useful.
How can I solve this circular references problem?
Serializing entities leads to a number of issues and exposes more information about your domain than is needed. When returning data to a view or an API consumer you can instead define a view model or DTO to contain just the details that consumer will need in whatever structure best serves that need. This avoids reference issues which EF navigation properties can cause, reduces the amount of domain knowledge and data you expose to clients, and minimizes the payload size to just what is needed. Data can be flattened, so if you are displaying a list of one entity, you don't need a ViewModel/DTO per related entity, your view model can merely contain relevant details of any related entity that applies to that consumer.
Once you have defined your view model / DTO you can use .Select() to populate it, or set up mapping with Automapper and populate it using .ProjectTo<TViewModel>().
I have an MVC 4 application that is using code first to generate tables and columns in my SQL Server DB. I am trying to figure out how I ended up with an additional TABLE that was not intended. I have looked through some questions but not found the exact same problem I am having. I will try to explain this simply.
I have added a model called Associate which keeps track of associates that my client does business with. Each Associate needs a foriegn key of AssociateTypedID and RegionID.
namespace XXX.Models
{
public class Associate
{
public int AssociateId { get; set; }
public string AssociateName { get; set; }
public int AddressNumber { get; set; }
public string AddressStreet { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zipcode { get; set; }
public string MainPhoneNumber { get; set; }
public string AssociateEmail { get; set; }
public string AssociateWebsite { get; set; }
public string ContactFirstName { get; set; }
public string ContactLastName { get; set; }
public string ContactPhoneNumber { get; set; }
public string ContactEmail { get; set; }
public int RegionId { get; set; }
public int AssociateTypeId { get; set; }
public virtual ICollection<AssociateType> AssociateTypes { get; set; }
public virtual ICollection<Region> Regions { get; set; }
}
}
AND
namespace XXX.Models
{
public class AssociateType
{
public int AssociateTypeId { get; set; }
public string AssociateTypeName { get; set; }
public virtual ICollection<Associate> Associates { get; set; }
}
}
AND
namespace XXX.Models
{
public class Region
{
public int RegionId { get; set; }
public int RegionName { get; set; }
public int RegionDescription { get; set; }
public virtual ICollection<Associate> Associates { get; set; }
}
}
AND
namespace XXX.Models
{
public class XXXDb : DbContext
{
public XXXDb(): base("name=DefaultConnection")
{
}
public DbSet<Associate> Associates { get; set; }
public DbSet<AssociateType> AssociateTypes { get; set; }
public DbSet<Region> Regions { get; set; }
}
}
So I have updated my code above and I'm getting very close to where I need to be in my database. I have the following tables generated.
Associates, AssociateTypes & Regions (each of them have the columns I would expect)
BUT I now have a new table called RegionAssociates which has the following columns:
Region_RegionId (int) & Associate_AssociateId (int)
This table was not expected or needed in my schema.
Your classes doesn't match your description of the model. You are saying
Each Associate can have a designation of AssociateType
I suppose that the same AssociateType can be assigned to more Associates, so there should be 1:N relationship between AssociateType and Associate.
But the Associate class defines the relationship the other way around - by convention public virtual ICollection<AssociateType> AssociateType { get; set; } creates 1:N relationship between Associate and AssociateType.
the correct definition of your classes would be
public class Associate
{
public int AssociateId { get; set; }
public string AssociateName { get; set; }
public int AddressNumber { get; set; }
public string AddressStreet { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zipcode { get; set; }
public string MainPhoneNumber { get; set; }
public string AssociateEmail { get; set; }
public string AssociateWebsite { get; set; }
public int RegionId { get; set; }
public int AssociateTypeId { get; set; }
public virtual AssociateType AssociateType { get; set; }
public string ContactFirstName { get; set; }
public string ContactLastName { get; set; }
public string ContactPhoneNumber { get; set; }
public string ContactEmail { get; set; }
public virtual ICollection<Region> Regions { get; set; }
}
public class AssociateType
{
public int AssociateTypeId { get; set; }
public string AssociateTypeName { get; set; }
public virtual ICollection<Associate> Associates { get; set; }
}
Can't say for sure what is missing from your configuration as you did't post it, but if you are using the fluent api something like this should fix the problem:
modelBuilder.Entity<AssociateType>()
.HasKey(t => t.AssociateTypeId);
modelBuilder.Entity<Associate>()
.HasRequired(t => t.AssociateType)
.WithRequiredPrincipal(t => t.Associate);
The above is adapted from this article http://msdn.microsoft.com/en-us/data/jj591620.aspx
I have the following Classes and am using EF 4.2 Code First
public class PartAttribute
{
public Part Part { get; set; }
public PartAttributeType PartAttributeType { get; set; }
[Timestamp]
public byte[] Time { get; set; }
[Required]
public string Value { get; set; }
}
public class Part
{
public Guid Id { get; set; }
[Required]
public PartType PartType { get; set; }
[Required]
public string SerialNumber { get; set; }
public string Description { get; set; }
public ICollection<Team> SelectedTeams { get; set; }
}
public class PartAttributeType
{
public Guid Id { get; set; }
[Required]
public PartType PartType { get; set; }
[Required]
public string Name { get; set; }
public string Description { get; set; }
}
When I build my model it creates the three tables and the relationships between the tables as I would like/expect them. I am trying to create a composite key on the PartAttribute table between the Part, PartAttributeType, and the time and I can't seem to figure it out. When I try to add
modelBuilder.Entity<PartAttribute>().HasKey(c => new { c.Part, c.PartAttributeType, c.Time });
I get an error saying Part is not a scalar type (which it is not).
You need to introduce foreign key properties which can act as primary keys at the same time:
public class PartAttribute
{
public Guid PartId { get; set; }
public Guid PartAttributeTypeId { get; set; }
public Part Part { get; set; }
public PartAttributeType PartAttributeType { get; set; }
[Timestamp]
public byte[] Time { get; set; }
[Required]
public string Value { get; set; }
}
Then your mapping:
modelBuilder.Entity<PartAttribute>()
.HasKey(c => new { c.PartId, c.PartAttributeTypeId, c.Time });
EF should be able to recognize the new properties as the foreign keys for your two navigation properties due to the naming convention.
I have a table in database which points to itself, i.e. parent_id >> category id. This is the ER diagram
I have modelled this table like following, but it gives *Error : 'Category': member names cannot be the same as their enclosing type :
public class Category
{
[Key]
public int category_id { get; set; }
public string category_name { get; set; }
public int category_parent { get; set; }
public string category_desc { get; set; }
public virtual Category Category { get; set; }
}
How should I model such tables ?
You have to make category_parent nullable and configure navigational property Category to the scalar property category_parent. Try to use proper naming convensions.
public class Category
{
[Key]
[Column("category_id")]
public int Id { get; set; }
[Column("category_name")]
public string Name { get; set; }
[Column("category_parent")]
public int? ParentId { get; set; }
[Column("category_desc")]
public string Description { get; set; }
[ForeignKey("ParentId")]
public virtual Category ParentCategory { get; set; }
}
I think you just need to change the Category property name to something else, so it is not the same as the class name...
public virtual Category SubCategory { get; set; }
public class Category
{
[Key]
public int category_id { get; set; }
public string category_name { get; set; }
public int category_parent { get; set; }
public string category_desc { get; set; }
public int parent_category_id { get; set; } <-- ADD & setup as foreign key
public virtual Category ParentCategory { get; set; } <-- Change name
public virtual ICollection<Category> Categories { get; set; }
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Category>.HasMany(cat => cat.Categories)
.WithRequired()
.HasForeignKey(cat => cat.parent_category_id);
}
I want to created Bi-Directional One-One relationship between two entities using EF Code First. I have trouble with the following code. What do you think I should do?
public class User
{
public string ID { get; set; }
public string LastName { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public int ProfileID { get; set; }
public Profile Profile { get; set; }
}
public class Profile
{
public int UserID { get; set; }
public User User { get; set; }
public int ProfileID { get; set; }
public string ProfileName { get; set; }
public DateTime CreateDate { get; set; }
public DateTime LastUpdateDate { get; set; }
}
I want to have both Navigation property and Foreign Key in both the entities.
This gives me error. What can do I in Fluent Mapping API to make this work?
Use this:
public class User
{
public string ID { get; set; }
public string LastName { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
public Profile Profile { get; set; }
}
public class Profile
{
[Key, ForeignKey("User")]
public int ProfileID { get; set; }
public string ProfileName { get; set; }
public DateTime CreateDate { get; set; }
public DateTime LastUpdateDate { get; set; }
public User User { get; set; }
}
That is the only valid way to build one-to-one relation in EF - PK of the dependent entity must be also FK to principal entity. There is nothing like bidirectional one-to-one relation in EF because it cannot work in EF.
The way how people sometimes overcome this are two one-to-many relations where principal doesn't have navigation collection for dependent entities + manually defined unique keys in the database. That require manual mapping:
public class User
{
public string ID { get; set; }
public string LastName { get; set; }
public string Password { get; set; }
public string FirstName { get; set; }
// one side MUST be nullable otherwise you have bidirectional constraint where each
// entity demands other side to be inserted first = not possible
public int? ProfileId { get; set; }
public Profile Profile { get; set; }
}
public class Profile
{
public int ProfileID { get; set; }
public string ProfileName { get; set; }
public DateTime CreateDate { get; set; }
public DateTime LastUpdateDate { get; set; }
public int UserId { get; set; }
public User User { get; set; }
}
And in mapping you will define:
modelBuilder.Entity<User>
.HasOptional(u => u.Profile)
.WithMany()
.HasForeignKey(u => u.ProfileId);
modelBuilder.Entity<Profile>
.HasRequired(u => u.User)
.WithMany()
.HasForeignKey(u => u.UserId);
Now you must define Unique keys in the database - if you are using code first use custom database initializer. Be aware that still bidirectional one-to-one is wrong concept because both sides demand unique FK where NULL is still included in unique values so once you insert User before Profile there mustn't be any other User without Profile. That probably leads to serializable transaction.