Configure Many to Many relationship - c#

For this I have 3 models: Hospitals, AspNetUsers, UserHospitals.
this is the UserHospitals model:
public class UserHospital
{
[Key]
public int UserHospitalID { get; set; }
public int HospitalID { get; set; }
public Hospital Hospitals { get; set; }
public string Id { get; set; }
public ApplicationUser Users { get; set; }
}
With it I can add User ID and Hospital ID to this table.
Now, I need to check which hospitals user's connected.
On my controller that return an hospital list i need to return only Hospitals that user's have a connection.
This return all hospitals, how can I filter it to show only if user have a connection with hospital on UserHospitals?
public ActionResult Index()
{
return View(db.Hospitals.ToList());
}
I don't want to add a new viewmodel that join models or whatever
== EDIT ==
Hospital Model
public class Hospital
{
[Key]
public int HospitalID { get; set; }
public string Name { get; set; }
public virtual ICollection<HospitalSpeciality> HospitalSpecialities { get; set; }
public virtual ICollection<UserHospital> UserHospitals { get; set; }
}

Try this:
public ActionResult Index()
{
var result =db.Hospitals.Include("UserHospitals").where(x=> x.UserHospitals.Any(x=>x.Id== userId)).ToList();
return View(result);
}

Related

Entity Framework 6 entity mapping

I am trying to write a simple CRUD on C#.
I am having troubles defining the relationships between these entities:
public class Movie
{
[Key]
public int Id { get; set; }
public string Title { get; set; }
public Director Director { get; set; }
}
public class Director
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Movie> DirectedMovies { get; set; }
}
How do I make it so that one director can have multiple movies and one movie can have one director?
The Movie table has the DirectorId column but I cannot find a way to add a director to the movie from the frontend side.
In MovieController, I have this code:
public ActionResult performAddMovie(Movie movie)
{
try
{
ctx.Movies.Add(movie);
ctx.SaveChanges();
return RedirectToAction("Index", "Home");
}
catch(Exception ex)
{
ModelState.AddModelError("Messaggio", ex.Message);
}
return RedirectToAction("Index", "Home");
}
This lets me add a new movie to the database, but I don't know how to add a director too.
Thank you
The Director is just another property. Presumably, before you pass a particular Movie object to performAddMovie, you're setting the title of the Movie.
If you've got the ID of Director, you can do:
var director = ctx.Directors.FirstOrDefault(d => d.Id == directorId);
movie.Director = director;
return performAddMovie(movie);
you have add DirectorId property in Movie class
Check this following code
Check this following code
public class Movie
{
public int Id { get; set; }
public string Title { get; set; }
public int DirectorId { get; set; }
[ForeignKey("DirectorId")]
public Director Director { get; set; }
}
public class Director
{
public int DirectorId { get; set; }
public string Name { get; set; }
public ICollection<Movie> DirectedMovies { get; set; }
}

.NET Mvc Web Application add SearchBox in Index for Many-to-Many table (intersection table)

I have the tables Film, Actor and ActorFilm which is an intersection table between Film and Actor and has the properties Id, FilmId, ActorId and navigation properties for Film and Actor.
This is my Film table
public partial class Film
{
public int Id { get; set; }
public string Title { get; set; }
public int Year { get; set; }
[Display(Name = "Actori")]
public virtual ICollection<ActorFilm> ActorFilms { get; set; }
}
This is my Actor table
public partial class Actor
{
public int Id { get; set; }
public string Nume { get; set; }
public virtual ICollection<ActorFilm> ActorFilms { get; set; }
}
This is my ActorFilm table
public partial class ActorFilm
{
public int Id { get; set; }
public int FilmId { get; set; }
public int ActorId { get; set; }
public virtual Actor ActorNavigation { get; set; }
public virtual Film FilmNavigation { get; set; }
}
This is my index action
public async Task<IActionResult> Index(){
var films = from f in _context.Film.Include(f => f.ActorFilms).ThenInclude(f => f.ActorNavigation)
select f;
return View(await films.AsNoTracking().ToListAsync());
}
I have my Index view page which displays all my films along with the actors that play in them. And I want to introduce a searchbox which allows me to search a film by the actor.
I tried with a ViewModel and I think this is part of the answer, but still failed. What should I do?

Which one is the correct one-to-many relation in EF

i am designing a system and one of my entity has one to many relation as shown below.
public class Product
{
public int Id { get; set; }
}
public class CompetitorProduct
{
public int Id { get; set; }
public Product Product { get; set; }
}
competitorProduct indicates that product has a equivalent which is sold by different store. should i define one-to-many relation as shown above or below? which one is correct?
public class Product
{
public int Id { get; set; }
public virtual ICollection<CompetitorProduct> CompetitorProducts{ get; set; }
}
public class CompetitorProduct
{
public int Id { get; set; }
}
Assuming it is a one to many relationship (what would happen if a competitor product was competing with more than one of your products for example) you can do both and add in a foreign key as well.
public class Product
{
public int Id { get; set; }
public virtual ICollection<CompetitorProduct> CompetitorProducts { get; set; }
}
public class CompetitorProduct
{
public int Id { get; set; }
public int ProductId { get; set; }
public virtual Product Product { get; set; }
}
You can then set up your relationship using fluent API as so:
modelBuilder.Entity<CompetitorProduct>(entity =>
{
entity.HasOne(e => e.Product)
.WithMany(e => e.CompetitorProducts)
.HasForeignKey(e => e.ProductId)
.HasConstraintName("FK_ComptetitorProduct_Product");
});
This way you can access the competitor products from the product and the product from the competitor products.
Here is a quick example of a ecommerce site I have worked on and how we did table relations.
I removed a bunch of the fields so you can see what you really need. Once to make relations and run Add-Migration EF will handle the FK constraints for you as long as you identified them in models like how I have below.
public class ApplicationUser : IdentityUser
{
public ApplicationUser()
{
Active = true;
CreateDateTimeUtc = DateTime.UtcNow;
ModifiedDateTimeUtc = DateTime.UtcNow;
}
[StringLength(500)]
public string FirstName { get; set; }
[StringLength(500)]
public string LastName { get; set; }
[StringLength(1000)]
public string Address { get; set; }
[StringLength(100)]
public string Unit { get; set; }
[StringLength(250)]
public string City { get; set; }
[StringLength(25)]
public string State { get; set; }
[StringLength(20)]
public string ZipCode { get; set; }
//This will give access to a list of child carts a user could have
[Index]
public bool Active { get; set; }
public virtual ICollection<Cart> Carts { get; set; }
// Account Profile Image
public byte[] ProfileImage { get; set; }
[StringLength(500)]
public string ProfileFilename { get; set; }
[StringLength(100)]
public string ProfileMimeType { get; set; }
}
[Table("Cart", Schema = "dbo")]
public class Cart : AbstractTable
{
public Cart()
{
IsComplete = false;
}
//This create relation to user table where I can get one unique user.
[StringLength(128)]
[ForeignKey("ApplicationUser")]
public string UserId { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
//These link us to child tables of Cart where we can get a LIST of the items below
public virtual ICollection<CartCategory> CartCategories { get; set; }
public virtual ICollection<CartItem> CartItems { get; set; }
// Marked when a payment/receipt is generated based off of this cart
public bool IsComplete { get; set; }
}
[Table("CartItem", Schema = "dbo")]
public class CartItem : AbstractTable
{
//This will return one unique cart id and let us access it as the parent record
[ForeignKey("Cart")]
public Guid CartId { get; set; }
public virtual Cart Cart { get; set; }
// Signifies if this was paid for in a receipt
public bool IsComplete { get; set; }
public virtual ICollection<CartItemCustomField> CustomFields { get; set; }
}

ASP.net MVC: PK and FK values are not in sync on lazy loading for one-to-many

I have the tables Company and Roles with one-to-many relation. I know that for lazy loading set-up the FK value of a Role entity should be automatically set to be in sync with his PK value of a Company. In the Company table I have a company entity instance added, but for some reason it is added null when I add a new role entity instance. What am I doing wrong?
These are my domain classes and the context:
public class Company
{
public Company()
{
Roles = new List<Role>();
Employees = new List<Employee>();
}
public int CompanyId { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string PhoneNo { get; set; }
public string Email { get; set; }
public virtual ICollection<Role> Roles { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
public class Role
{
public Role()
{
RoleOverviews = new List<RoleOverview>();
}
public int RoleId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual Company Company { get; set; }
public ICollection<RoleOverview> RoleOverviews { get; set; }
}
public class AppDbContext:DbContext
{
public DbSet<Company> Companies { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<RoleOverview> RoleOverviews { get; set; }
public AppDbContext() : base("DefaultConnection")
{
}
}
public ActionResult Create([Bind(Include = "RoleId,Name,Description")] Role role)
{
if (ModelState.IsValid)
{
db.Roles.Add(role);
db.SaveChanges();
return RedirectToAction("Index", "CompaniesRolesMV");
}
return View(role);
}
The PK_FK relationship you have defined will only make certain that the company field in your Role table will have a valid ID. but it cannot 'guess' which company it belongs to unless the code tells it.
the Role you are defining/creating in your 'Create' method needs to have a CompanyID value supplied. Presumably, the user will have a choice from a Selector (?)
you probably need t define a Company selector in your View and your Create Method Action should include the CompanyID from that selector:
public ActionResult Create([Bind(Include = "RoleId,Name,Description,CompanyID")] Role role)
{
if (ModelState.IsValid)
{
db.Roles.Add(role);
db.SaveChanges();
return RedirectToAction("Index", "CompaniesRolesMV");
}
return View(role);
}

Add a navigation property to a plain object

So I have a viewmodel in my application that looks like:
public class CountryVM
{
[Key]
public int CountryID { get; set; }
[ForeignKey("Country_CountryID")]
public virtual ICollection<OrganisationVM> Organisations { get; set; }
public CountryVM(Country country)
{
if (country == null) return;
this.CountryID = country.CountryID;
}
}
That is seeded by the class:
public class Country
{
[Key]
public int CountryID { get; set; }
public virtual ICollection<Organisation> Organisations { get; set; }
}
The other relevant classes are:
public class Organisation
{
[Key]
public int OrganisationId { get; set; }
[Required]
public virtual Country Country { get; set; }
}
public class OrganisationVM
{
[Key]
public int OrganisationId { get; set; }
[ForeignKey("Country_CountryID")]
public virtual CountryVM Country { get; set; }
public int? Country_CountryID { get; set; }
}
Now Organisation and Country are tables in my database and OrganisationVM is a view. CountryVM exists only in the application and at the moment EF tries to create a table in my database 'dbo.CountryVMs'.
Is there anyway to hook it up like this so I can use a navigation property in CountryVM without it creating tables?
The reason I want to do this is:
I have this code in my web.api controller at the moment:
// GET: odata/Country
[EnableQuery]
public IQueryable<CountryVM> Get()
{
var a = db.Countries.ToList().Select<Country, CountryVM>(c => new CountryVM(c)).AsQueryable();
return a;
}
I was hoping that odata would allow me to use expand and select to select the countryVMs Organisations but it hasn't so far.

Categories