I'm trying to delete the entities related to each other when I remove a row, but it isn't deleting the related entities. It is only deleting one entity and not the others.
My model
public class Company
{
public int CompanyId { get; set;}
public string CompanyName { get; set; }
public int CompanySize { get; set; }
public string Branche { get; set;}
public string Description {get; set;}
public Recruiter Recruiter { get; set; }
public ICollection<Post> Posts { get; set; }
}
public class Recruiter
{
public int RecruiterId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public string PhoneNumber { get; set; }
public int CompanyId { get; set; }
public Company Company { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Location { get; set; }
public int Compensation { get; set; }
public string Education { get; set; }
public string StartDate { get; set; }
public string Type { get; set; }
public string Profession { get; set; }
public string Language { get; set; }
public string Description { get; set; }
public string Hours { get; set; }
public bool Checked { get; set; }
public int CompanyId { get; set; }
public Company Company { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Post>()
.HasOne(post => post.Company)
.WithMany(company => company.Posts)
.IsRequired()
.OnDelete(DeleteBehavior.Cascade);
modelBuilder.SeedDatabase();
}
The call I make. So when I delete a post, I want that all the related entities are being deleted.
public Post DeclinePostRequest(int postId)
{
var request = _dbContext.Posts.Where(post => post.PostId == postId).Include(post => post.Company).ThenInclude(company => company.Recruiter).FirstOrDefault();
if(!request.Checked)
{
_dbContext.Posts.Remove(request);
_dbContext.SaveChanges();
return request;
}
return null;
}
You are deleting the many side of a 1-to-many relationship there. Everything is working as expected.
Try deleting a Company instead.
Related
I have three related Entities in my blazor application Opportunity, AppUser and AssignedOpportunity, What I want to achieve is to map Opportunity and AppUser to a DTO Object ReturnAssignedOpportunityDTO which has similar fields as the entities, using AutoMapper, but am not sure how to do that, below are the entities
public partial class AssignedOpportunity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
[ForeignKey("OpportunityID")]
public string OpportunityID { get; set; }
public string Status { get; set; }
public Opportunity opportunity { get; set; }
[ForeignKey("UserID")]
public string UserID { get; set; }
public AppUser User { get; set; }
}
The opportunity
public partial class Opportunity
{
public Opportunity()
{
AssignedOpportunities= new HashSet<AssignedOpportunity>();
}
[Key]
public string ID { get; set; }
public string OpportunityName { get; set; }
public string Description { get; set; }
public string CreatedBy { get; set; }
public DateTime DateCreated { get; set; }
public double EstimatedValue { get; set; }
public string EmployeeNeed { get; set; }
public double RealValue { get; set; }
public string Location { get; set; }
public string ReasonStatus { get; set; }
public string Status { get; set; }
public virtual ICollection<AssignedOpportunity> AssignedOpportunities { get; set; }
}
AppUser Class
public partial class AppUser : IdentityUser
{
public AppUser()
{
AssignedOpportunities = new HashSet<AssignedOpportunity>();
}
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string Gender { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string LGA { get; set; }
public string State { get; set; }
public virtual ICollection<AssignedOpportunity> AssignedOpportunities { get; set; }
}
Here's the DTO Object I want to map to.
public class ReturnOpportunitiesDTO
{
public int ID { get; set; }
public string OpportunityID { get; set; }
public string OpportunityName { get; set; }
public double EstimatedValue { get; set; }
public string EmployeeNeed { get; set; }
public double RealValue { get; set; }
public string Location { get; set; }
public string UserID { get; set; }
public string UserFullName { get; set; }
public string Status { get; set; }
}
Here is my query to fetch the records
var result = await _context.AssignedOpportunities.Include(o => o.opportunity).
ThenInclude(a => a.User).
Where(a=>a.UserID==UserID.ToString()).ToListAsync();
return result;
This is how i usually setup Map Profile
public AssignArtisanProfile()
{
CreateMap<AssignedOpportunity, ReturnOpportunities>();
}
But since I want to map multiple entities, how do I include the other entity
Your scenario is just another example of flattening a complex object. You have properties in child objects, which you want to bring to the ground level, while still leveraging AutoMapper mapping capabilities. If only you could reuse other maps from app user and opportunity when mapping from assigned opportunity to the DTO... Well, there is a method called IncludeMembers() (see the docs) that exists precisely for such case. It allows you to reuse the configuration in the existing maps for the child types:
config.CreateMap<AssignedOpportunity, ReturnOpportunitiesDTO>()
.IncludeMembers(source => source.opportunity, source => source.User);
config.CreateMap<Opportunity, ReturnOpportunitiesDTO>();
config.CreateMap<AppUser, ReturnOpportunitiesDTO>()
.ForMember(
dest => dest.UserFullName,
options => options.MapFrom(source =>
string.Join(
" ",
source.FirstName,
source.MiddleName,
source.LastName)));
Usage:
var mappedDtos = mapper.Map<List<ReturnOpportunitiesDTO>>(assignedOpportuniesFromDatabase);
I have User table and I'd like to add connection called UserFriend between 2 users. I've searched a lot and basicly tried many different solutions and none of them worked. Everytime I get same error:
Introducing FOREIGN KEY constraint 'FK_UserFriends_Users_Friend2Id' on table 'UserFriends' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Here are my models:
public class User
{
[Key]
public Guid Id { get; set; }
public string Username { get; set; }
public string EmailAddress { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public virtual ICollection<UserFriend> Friends { get; set; }
public virtual ICollection<UserFriend> FriendOf { get; set; }
}
public class UserFriend
{
public User Friend1 { get; set; }
public Guid Friend1Id { get; set; }
public User Friend2 { get; set; }
public Guid Friend2Id { get; set; }
public bool Confirmed { get; set; }
public DateTime Added { get; set; }
}
And here's code in DataContext:
modelBuilder.Entity<UserFriend>().HasKey(sc => new { sc.Friend1Id, sc.Friend2Id });
modelBuilder.Entity<UserFriend>()
.HasOne(c => c.Friend1)
.WithMany(c => c.FriendOf)
.HasForeignKey(f => f.Friend1Id);
modelBuilder.Entity<UserFriend>()
.HasOne(c => c.Friend2)
.WithMany(c => c.Friends)
.HasForeignKey(f => f.Friend2Id)
.OnDelete(DeleteBehavior.Restrict);
Change your code to below and remove the other lines you have posted.
public class User
{
[Key]
public Guid Id { get; set; }
public string Username { get; set; }
public string EmailAddress { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public virtual ICollection<UserFriend> Friends { get; set; }
public virtual ICollection<UserFriend> FriendOf { get; set; }
}
public class UserFriend
{
public User Friend1 { get; set; }
[ForeignKey("Friend1")]
public Guid? Friend1Id { get; set; }
public User Friend2 { get; set; }
[ForeignKey("Friend2")]
public Guid? Friend2Id { get; set; }
public bool Confirmed { get; set; }
public DateTime Added { get; set; }
}
modelBuilder.Entity<User>();
modelBuilder.Entity<UserFriend>();
I have two classes:
One is User
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public List<Subscription> Subscriptions { get; set; }
}
Other is Subscription:
public class Subscription
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
As you can see that User has a list of Subscriptions.
Now when using the entity framework code first approach I am getting a table for User which doesn't contain Subscriptions but a new column for User Id is being added to Subscription table. I was expecting to have a third table which contains two columns one with User ID and the other with subscription ID.
How can I achieve this?
From documentation:
Many-to-many relationships without an entity class to represent the join table are not yet supported. However, you can represent a many-to-many relationship by including an entity class for the join table and mapping two separate one-to-many relationships.
So this answer is correct.
I just corrected code a little bit:
class MyContext : DbContext
{
public DbSet<Use> Users { get; set; }
public DbSet<Subscription> Subscriptions { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<UserSubscription>()
.HasKey(t => new { t.UserId, t.SubscriptionId });
modelBuilder.Entity<UserSubscription>()
.HasOne(pt => pt.User)
.WithMany(p => p.UserSubscription)
.HasForeignKey(pt => pt.UserId);
modelBuilder.Entity<UserSubscription>()
.HasOne(pt => pt.Subscription)
.WithMany(t => t.UserSubscription)
.HasForeignKey(pt => pt.SubscriptionId);
}
}
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public List<UserSubscription> UserSubscriptions{ get; set; }
}
public class Subscription
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public List<UserSubscription> UserSubscriptions{ get; set; }
}
public class UserSubscription
{
public int UserId { get; set; }
public User User { get; set; }
public int SubscriptionId { get; set; }
public Subscription Subscription { get; set; }
}
PS. You don't need use virtual in navigation property, because lazy loading still not available in EF Core.
Create a third middle table named: UserSubscriptions for example.
public class User
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public virtual ICollection<UserSubscription> Subscriptions { get; set; }
}
public class Subscription
{
public int ID { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
public class UserSubscription
{
public int ID { get; set; }
public int SubscriptionID { get; set; }
public decimal Price { get; set; }
public int UserID { get; set; }
public virtual User { get; set; }
public DateTime BeginDate { get; set; }
public DateTime EndDate { get; set; }
}
Second Solution:
Add reference for Subscription to User and name it CurrentSubscription for example.
public class User
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public int CurrentSubscriptionID { get; set; }
public virtual Subscription Subscription { get; set; }
}
public class Subscription
{
public int ID { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
I want to have a one to many relationship in between instructor and course. How can I achieve it? Below is what I have as of now.
public class Instructor
{
//[Key]
public int id { get; set; }
public string name { get; set; }
public string address { get; set; }
public string email { get; set; }
}
public class Course
{
//[Key]
public int id { get; set; }
[DisplayName("Course")]
[Required(ErrorMessage = "CSExxx")]
public string progId { get; set; }
public string name { get; set; }
public string semester { get; set; }
public string description { get; set; }
public virtual Instructor instructor { get; set; }
}
You need to add a virtual collection of Course to Instructor
public class Instructor
{
//[Key]
public int id { get; set; }
public string name { get; set; }
public string address { get; set; }
public string email { get; set; }
public virtual ICollection<Course> Courses { get; set; }
}
public class Course
{
//[Key]
public int id { get; set; }
[DisplayName("Course")]
[Required(ErrorMessage = "CSExxx")]
public string progId { get; set; }
public string name { get; set; }
public string semester { get; set; }
public string description { get; set; }
public virtual Instructor instructor { get; set; }
}
In OnModelCreating in your DataContext
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Instructor>().HasMany(i => i.Courses).WithRequired(c => c.Instructor).HasForeignKey(c => c.instructor).WillCascadeOnDelete(true);
}
I have few Domain Models - Address, Customer, Employee, StoreLocation. Address has many to one relationship with Customerand Employee and one to one relationship with StoreLocation.
public class Address
{
public int Id;
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Line3 { get; set; }
}
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public IList<Address> Addresses { get; set; }
}
public class StoreLocation
{
public int Id { get; set; }
public string ShortCode { get; set; }
public string Description { get; set; }
public Address Address { get; set; }
}
public class Employee
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime Dob { get; set; }
public IList<Address> Addresses { get; set; }
}
How to Map this relationship?. I am using ASP.NET MVC 3.0 and Entity Framework 4.1.
If you are using code-first (I think you want this, else, you have to edit your Q), the first way is the way explained below:
Entities:
public class Address {
[Key]
public int Id { get; set; }
public string Line1 { get; set; }
public string Line2 { get; set; }
public string Line3 { get; set; }
public virtual Customer Customer { get; set; }
public virtual StoreLocation StoreLocation { get; set; }
public virtual Employee Employee { get; set; }
public int? CustomerId { get; set; }
public int? EmployeeId { get; set; }
}
public class Customer {
[Key]
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
}
public class StoreLocation {
[Key]
public int Id { get; set; }
public string ShortCode { get; set; }
public string Description { get; set; }
public virtual Address Address { get; set; }
}
public class Employee {
[Key]
public int Id { get; set; }
public string Name { get; set; }
public DateTime Dob { get; set; }
public virtual ICollection<Address> Addresses { get; set; }
}
DbContext inherited class:
public class ManyOneToManyContext : DbContext {
static ManyOneToManyContext() {
Database.SetInitializer<ManyOneToManyContext>(new ManyOneToManyInitializer());
}
public DbSet<Address> Addresses { get; set; }
public DbSet<Customer> Customers { get; set; }
public DbSet<StoreLocation> StoreLocations { get; set; }
public DbSet<Employee> Employees { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder) {
modelBuilder.Conventions.Remove<IncludeMetadataConvention>();
modelBuilder.Entity<Customer>().HasMany(c => c.Addresses).WithOptional(a => a.Customer).HasForeignKey(a => a.CustomerId);
modelBuilder.Entity<StoreLocation>().HasRequired(s => s.Address).WithOptional(a => a.StoreLocation).Map(t => t.MapKey("AddressId"));
modelBuilder.Entity<Employee>().HasMany(e => e.Addresses).WithOptional(a => a.Employee).HasForeignKey(e => e.EmployeeId);
}
}
Context Initializer:
public class ManyOneToManyInitializer : DropCreateDatabaseAlways<ManyOneToManyContext> {
protected override void Seed(ManyOneToManyContext context) {
}
}
That will create the db-schema below:
Let me know if you have any questions or need clarifications on any part.