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.
Related
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.
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.
I have domain model like this
public class EntityOne
{
public int EnityOneId { get; set; }
public int EntityOnePropertyOne { get; set; }
public List<EntityTwo> EntityTwos { get; set; }
}
public class EntityTwo
{
public int EntityTwoId { get; set; }
public string EntityTwoPropertyOne { get; set; }
public int EntityThreeId { get; set; }
public int EnityOneId { get; set; }
public virtual EntityOne EntityOne { get; set; }
public virtual EntityThree EntityThree { get; set; }
}
public class EntityThree
{
public int EntityThreeId { get; set; }
public string EntityThreePropertyOne { get; set; }
}
and I have DTO like this
public class EntityDTO
{
public int EntityOnePropertyOne { get; set; }
public string EntityThreePropertyOne_ValueOne { get; set; }
public string EntityThreePropertyOne_ValueTwo { get; set; }
public string EntityThreePropertyOne_ValueThree { get; set; }
public string EntityThreePropertyOne_ValueFour { get; set; }
public string EntityThreePropertyOne_ValueFive { get; set; }
}
I want to configure mapping from DTO to DomainModel and the reverse using AutoMapper but I didnt know how to do that... any suggestion or help
I'm not sure what you're trying to accomplish here.
I get that you want to map to EntityDTO, but from what other type? I will assume you want to use EntityTwo as the source.
In that case,
EntityOnePropertyOne: Will be obtained automatically via Flattening from the source (EntityTwo) - So, no problem here.
EntityThreePropertyOne_ValueOne: This will assume you have a property called EntityThree (which you do), and within that type, a property called PropertyOne_ValueOne of type int (which you don't). Same applies for the rest.
The other way around will get trickier, since I see there will be lots of properties ignored, so you need to tell AutoMapper, that you don't want it to be concerned about all that bunch of properties in your complex type, that don't come from the DTO.
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.
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);