Entity Framework 6 entity mapping - c#

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; }
}

Related

.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?

Entity Framework: How do I delete table rows that reference each other?

How do I delete the order without getting this exception?
UserLicenses references SerialOnOrderDetails and vice-versa:
The DELETE statement conflicted with the REFERENCE constraint "FK_SerialsOnOrderDetail_UserLicenses". The conflict occurred in database "sales", table "dbo.SerialsOnOrderDetail", column 'UserLicenseId'.
Delete confirmed controller action code:
[Authorize(Roles = "admin")]
[HttpPost, ActionName("Delete")]
public async Task<ActionResult> DeleteConfirmed(int id)
{
Order order = GetOrderById(id);
if (order.UserLicenses.Count > 0)
{
context.UserLicenses.RemoveRange(order.UserLicenses);
}
if (order.SerialsOnOrderDetails.Count > 0)
{
context.SerialsOnOrderDetails.RemoveRange(order.SerialsOnOrderDetails);
}
context.Orders.Remove(order);
context.SaveChanges(); // Exception here !!!
}
[EDIT] Added live data
Live data (Id = UserLicenseId):
Additional classes:
public partial class UserLicense
{
public string Id { get; set; }
public int OrderId { get; set; }
public string ProductId { get; set; }
public int CustomerId { get; set; }
public string AssignedUserId { get; set; }
public bool IsActive { get; set; }
public virtual AspNetUser AspNetUser { get; set; }
public virtual Customer Customer { get; set; }
public virtual Order Order { get; set; }
public virtual Product Product { get; set; }
public virtual ICollection<SerialsOnOrderDetail> SerialsOnOrderDetails { get; set; }
}
public partial class SerialsOnOrderDetail
{
public int orderID { get; set; }
public string serial { get; set; }
public string productID { get; set; }
public string UserLicenseId { get; set; }
public int customerID { get; set; }
public virtual Product Product { get; set; }
public virtual Serial Serial1 { get; set; }
public virtual Order Order { get; set; }
public virtual UserLicense UserLicense { get; set; }
public virtual Customer Customer { get; set; }
}
public partial class Order
{
public Order()
{
this.OrderDetails = new HashSet<OrderDetail>();
this.SerialsOnOrderDetails = new HashSet<SerialsOnOrderDetail>();
this.UserLicenses = new HashSet<UserLicense>();
}
public int orderID { get; set; }
public int customerID { get; set; }
public string promoCodeID { get; set; }
public System.DateTime date { get; set; }
public Nullable<int> resellerID { get; set; }
public string invoiceID { get; set; }
public string poNumber { get; set; }
public Nullable<System.DateTime> paymentDate { get; set; }
public Nullable<bool> validated { get; set; }
public string resellerOrderID { get; set; }
public Nullable<int> parentOrderID { get; set; }
public int months { get; set; }
public virtual Customer Customer { get; set; }
public virtual ICollection<OrderDetail> OrderDetails { get; set; }
public virtual PromoCode PromoCode { get; set; }
public virtual Reseller Reseller { get; set; }
public virtual ICollection<SerialsOnOrderDetail> SerialsOnOrderDetails { get; set; }
public virtual Order ParentOrder { get; set; }
public virtual ICollection<UserLicense> UserLicenses { get; set; }
}
Did you verify if UserLicenses and SerialsOnOrderDetails collections are properly loaded and not empty ? Are you sure removerange is the proper way to do it ? I suggest you to read a few tutorials about EF if you are not used to it.
Maybe you'll have to update GetOrderById with .Include("....") directives to load these collections, or load the related items manually.
That constraint message you quote is from the underlying SQL Server. It's not an EF error as such, it's passed through.
When I get this sort of problem in TSQL the solution is generally to delete both of the mutually referencing rows in a single transaction.
While I'm not terribly familiar with EF, a quick search turn up this example of putting multiple operations into a single transactional context instead of the default behaviour of a single transaction per operation.
{
context.Database.Log = Console.WriteLine;
using (DbContextTransaction transaction = context.Database.BeginTransaction())
{
try
{
Author author1 = new Author() { Name = "Mark" };
Author author2 = new Author() { Name = "John" };
context.Authors.Add(author1);
context.SaveChanges();
context.Authors.Add(author2);
context.SaveChanges();
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
}
}
}
I notice another respondent describes other things that could be wrong. It is entirely possible that we are both right and there are multiple issues to resolve.

How to write a get method for data with a many-to-many relationship

I have two entities connected by a many-to-many relationship.
First class:
public class Movie
{
public int Id { get; set; }
public string Title { get; set; }
public List<MovieActor> MovieActor { get; set; }
}
Second class:
public class Actor
{
public int Id { get; set; }
public string Name { get; set; }
public List<MovieActor> MovieActor { get; set; }
}
And relationship (many to many):
public class MovieActor
{
public int MovieId { get; set; }
public Movie Movie { get; set; }
public int ActorId { get; set; }
public Actor Actor { get; set; }
}
I want to write the IEnumerable<Movie> GetMovies(int actorId) method, which takes the actor's id as the parameter. I would like the method to return a list of movies in which an actor with the given Id plays. How can I do that?
You do not need the MovieActor class
Change to:
public class Movie
{
public int Id { get; set; }
public string Title { get; set; }
public List<Actor> Actors { get; set; }
}
public class Actor
{
public int Id { get; set; }
public string Name { get; set; }
public List<Movie> Movies { get; set; }
}
Then you can select the Actor and you have the list of Movies as a property on the actor.
so you can do something like this
public IEnumerable<Movie> GetMovies(int actorId)
{
var result = await _context.Actor.Where(x => x.Id == actorId).
Include(x => x.MovieActor).ThenInclude(x => x.Movie).FirstOrDefaultAsync();
var movies = result.MovieActor.select(x => x.Movie).Tolist();
return movies
}

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; }
}

Entity Framework Conditional join

I have created an MVC using Entity framework and I've encountered a situation which I don't know how to resolve.
I'm using the EF auto joins and relations (all my table models were created automatically by EF) .
Now for the problem - I have a table of customers, which has two(relavent) fields - personID and employerID . Only one of them contains data , the other will be null (a customer is either a person , or an employer) . When I try to include employer model in the result set, I'm getting thrown (without any message , when I debug I see that the content has data but the employeer is sometimes NULL) I'm also not sure about how the design should look like. This is my code :
Customer:
public partial class Customer
{
public Customer()
{
Account = new HashSet<Account>();
}
public long Id { get; set; }
public int? PersonId { get; set; }
public int Type { get; set; }
public int? EmployerId { get; set; }
public Employer Employer { get; set; }
public ICollection<Account> Account { get; set; }
}
Employer:
public partial class Employer
{
public Employer()
{
Customer = new HashSet<Customer>();
}
public int Id { get; set; }
public string Name { get; set; }
public int? IdType { get; set; }
public ICollection<Customer> Customer { get; set; }
}
Person:
public partial class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Sex { get; set; }
public DateTime? BirthDate { get; set; }
public int IdType { get; set; }
}
Now when I'm running in my repository:
var collectionBeforePaging = _context.Customer
Everything works, but Employer is NULL. If I use :
var collectionBeforePaging = _context.Customer.Include(a => a.Employer)
Then the project fails .
How can I make this joins?
Please define ForeignKey for Customer
public int? EmployerId { get; set; }
[ForeignKey(nameof(EmployerId))]
public virtual Employer Employer { get; set; }
What version of EF you use? I think you missing something like that :
In Employer :
[ForeignKey("EmployerId")]
[InverseProperty("Customers")]
public virtual Employer Employer { get; set; }
public int? EmployerId { get; set; }
In Customer :
[InverseProperty("Employer")]
public virtual ICollection<Customer> Customers { get; set; }
It can also be done in the Dbontext object

Categories