Entity Framework Core Navigation Properties and Joins, Correct Pattern - .net-core

I'm struggling to understand the best way to implement some database relationships in EF Core.
Specifically, it involves the navigation properties, where you make a collection in the parent and an object in the child.
Looking at the MS docs here
Relationships, navigation properties, and foreign keys
there is the typical use case presented of a parent child relationship
public class Course
{
public int CourseID { get; set; }
public string Title { get; set; }
public int Credits { get; set; }
public int DepartmentID { get; set; }
public virtual Department Department { get; set; }
}
public class Department
{
public Department()
{
this.Courses = new HashSet<Course>();
}
public int DepartmentID { get; set; }
public string Name { get; set; }
public decimal Budget { get; set; }
public DateTime StartDate { get; set; }
public virtual ICollection<Course> Courses { get; set; }
}
Now this is fine for the above use case.
However, I am working on a specification system for process recipes. There are lots of machines, materials, areas, buildings and other things involved.
One of the tables in the database is "Unit", as in unit of measurement - that is kg, m, cm, etc.
This table is used as a lookup in many tables in the database, at least 20.
As such, if I've understood the recommended approach, I would end up with
pubic class Unit
{
public Guid Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Recipes> Recipes{ get; set; }
public virtual ICollection<Coll2> Coll2{ get; set; }
public virtual ICollection<Coll3> Coll2{ get; set; }
public virtual ICollection<Coll4> Coll2{ get; set; }
public virtual ICollection<Coll5> Coll2{ get; set; }
public virtual ICollection<Coll..n> Coll..n{ get; set; }
}
This applies not just for unit, but also for quite a few other generic lookup items, such as a warehouse. There are many entities that use a link to the warehouse.
What is the correct approach when using this kind of lookup?
I'm sorry if things aren't clear, hopefully they are.

Related

ASP.NET MVC 6 Update Multiple Tables from One View

I’m coming from an intermediate C++ background (and to a lesser extent, C#) and wanted to try to build a project in Asp.net MVC 6 with EF 7 – not realizing how completely different it is from simple C# forms. I’ve stumbled through and researched a lot but since I’m a total noob I’m stumped at this point.
I have the following models:
public class Shift
{
public int ShiftId { get; set; }
//other properties
public virtual ICollection<ShiftActivity> ShiftActivity { get; set;}
}
public class ShiftActivity
{
public int ShiftActivityID { get; set; }
public DateTime StartTime { get; set; }
public int ShiftID { get; set; }
public int ActivityID { get; set; }
public int LocationID { get; set; }
public virtual Shift Shift { get; set; }
public virtual Activity Activity { get; set; }
public virtual Location Location { get; set; }
}
public class Activity
{
public int ActivityID { get; set; }
public string ActivityName { get; set; }
public virtual ICollection<ShiftActivity> ShiftActivity { get; set; }
}
public class Location
{
public int LocationID { get; set; }
public string LocationName { get; set; }
public string LocationAddress { get; set; }
public int locationZip { get; set; }
public virtual ICollection<ShiftActivity> ShiftActivity { get; set; }
}
I would like to create a shift and be able to input all the required fields all from one view. For instance, when I create the shift, I need to pick the type of location and activity to add to the ShiftActivity table which is then updated. Eventually I would like to be able to dynamically add additional activities (I’m assuming I’ll need javascript for that), but that’s another issue. I know I need a viewmodel to access all the tables, but I’m unclear as to how the viewmodel should be structured correctly.
Also, can the ShiftController update the ShiftActivity table directly or do I need to transfer the data somehow to the ShiftAcitivityController when the form is submitted? Either way, can someone point me to an example? Thank you… Any help is greatly appreciated.

Accessing different models from controllers

I'm pretty new to MVC, it's my first project and I'm trying to learn best practices. I'm using Entity Framework.
Here is the thing:
I have two models, one is for overtime work records and other one for accounting records.
When I create an overtime work record, I want to create an accounting record too. So lets say I created overtime record with 2 hours of work, I want to create an accounting record with value of "hours of work (2) * employees overtime work salary".
I can easily do this in OvertimeController's create method but I'm not sure if I should access other models (Accounting Model) from that controller.
What's the best way to do it?
Here is my models, i'm using code first:
Accounting
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int AccountingId { get; set; }
public decimal AccountingType { get; set; }
public decimal AccountingMethod { get; set; }
public string AccountingNote { get; set; }
public decimal AccountingBorc { get; set; }
public decimal AccountingAlacak { get; set; }
public decimal WorkerId { get; set; }
public decimal PhaseId { get; set; }
public virtual Worker Worker { get; set; }
public virtual Phase Phase { get; set; }
Overhours
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int OverhourId { get; set; }
public int WorkerId { get; set; }
public int PhaseId { get; set; }
public int OverhourAmount { get; set; }
public DateTime OverhourDate { get; set; }
public virtual Worker Worker { get; set; }
public virtual Phase Phase { get; set; }
Thanks

Alter primary key with Entity Framework

First of all ASP.NET and MVC 4 are very new to me (+- one month) and sorry if its a bad question.
I've got two classes "Turma" and "Curso"
public class Turma
{
[Key]
public int idCurso { get; set; }
public string RefTurma { get; set; }
public Curso Curso { get; set; }
public string NomeCurso { get; set; }
}
and
public class Curso
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int idArtigoAT { get; set; }
public string ConteudoPrograma { get; set; }
public virtual ICollection<Turma> Turmas { get; set; }
}
After this I started a migration and updated the database. So far so good, but then problems.
Due to new information the primary key type should be varchar(18). I've tried to change but so far without success.
Any ideia or solution???
No, what you want is an 'Id' property and an 'MyCustomUniqueName' property. this custom property, should be and unique index in database. this is the best design for this situation IMHO.

EF 5.0 Code First mapping issues between 3 entities

I've got 2 entities:
public class School
{
public int Id { get; set; }
...
public virtual ICollection<Seminar> Seminars { get; set; }
}
public class Seminar
{
public int Id { get; set; }
...
public virtual ICollection<School> Schools { get; set; }
public virtual ICollection<Price> Prices { get; set; } // wrong??
}
public class Price
{
public int Id { get; set; }
public decimal Value { get; set; }
public virtual School School { get; set; }
public virtual Seminar Seminar { get; set; }
}
How to map "Price" property for getting something like this:
var priceOfSomeSeminar = someSchool.Seminars[0].Price
Is it possible? So I think I need help with the Fluent API modelBuilder relationship establishment...
Well, ICollection doesn't have an indexer, so you can't use array syntax with it. You can, however, convert it to an IEnumerable and then convert that to a List, which can then be indexed.
But no, you are using the correct semantics, so this should just work. No need to work with the fluent api.
I think you have an error though, Price should not have a School member. There is no direct relationship between price and school.

MVC EF Code First one to one relationship error

I want to have a list of stands (at a trade show) and a list of exhibitors.
The list of stands is separate to the list of exhibitors - however, once registered, I want the exhibitor to be able to book a stand.
When they select/book a stand - I would like to then be able to have a list the stands in my view, and also show the associated exhibitor who has booked it.
Likewise, I would like to list in another view, the exhibitors, and also which stand they have booked.
So I'm trying to setup a one to one relationship (using EF CodeFirst).
However, when trying to add a controller for either the Stand or the Exhibitor, I get the following error:
My models are:
public class Stand
{
public int StandID { get; set; }
public string Description { get; set; }
public bool Booked { get; set; }
public int ExhibitorID { get; set; }
public virtual Exhibitor Exhibitor { get; set; }
}
public class Exhibitor
{
public int ExhibitorID { get; set; }
public string Company { get; set; }
public int StandID { get; set; }
public virtual Stand Stand { get; set; }
}
I'm certain it's something to do with the "Virtual" part of the models.
Can anyone please help point out what should be updated, to allow the connection?
Thank you,
Mark
EF doesn't know which entity is the principal (parent) and which is the dependent (child). You need to declare a foreign key on the item that entity that should come first. You can do this with an annotation or a fluent mapping.
Annotation
Add the following namespace:
using System.ComponentModel.DataAnnotations.Schema;
Annotate your Stand class with the following annotation:
public class Stand
{
[ForeignKey("Exhibitor")]
public int StandID { get; set; }
public string Description { get; set; }
public bool Booked { get; set; }
public int ExhibitorID { get; set; }
public virtual Exhibitor Exhibitor { get; set; }
}
Fluent Mapping
Override your OnModelCreating method in your DbContext class to include:
modelBuilder.Entity<Stand>()
.HasOptional(s => s.Exhibitor)
.WithRequired(e => e.Stand);
The model you have created is not possible to work with relational databases. The Stand needs an ExibitorId while Exibitor need a StandId. The cyclic relationship does not allow you to insert any rows to either tables.
Assuming an Exibitor may have more than one Stand and converting the relationship to one-to-many is one option.
public class Stand
{
public int StandID { get; set; }
public string Description { get; set; }
public bool Booked { get; set; }
public int? ExhibitorID { get; set; }
public virtual Exhibitor Exhibitor { get; set; }
}
public class Exhibitor
{
public int ExhibitorID { get; set; }
public string Company { get; set; }
public virtual ICollection<Stand> Stands { get; set; }
}
Or you can use shared primary key mapping to make the relationship one-to-one. Where Stand is the principal entity. The Exibitor will use the StandID as its PK.
public class Stand
{
public int StandID { get; set; }
public string Description { get; set; }
public bool Booked { get; set; }
public virtual Exhibitor Exhibitor { get; set; }
}
public class Exhibitor
{
public int ExhibitorID { get; set; }
public string Company { get; set; }
public virtual Stand Stand { get; set; }
}
Using the Fluent API to configure the relationship.
modelBuilder.Entity<Exibitor>().HasRequired(e => e.Stand)
.WithOptional(s => s.Exibitor);

Resources