I have two tables in my SQL Server database - one for categories:
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public int? ParentId { get; set; }
[ForeignKey("ParentId")]
public Category Parent { get; set; }
}
And then the Assistant table:
public class Assistant
{
public int Id { get; set; }
public int UserId { get; set; }
public DateTime CreatedAtUtc { get; set; }
public Status Status { get; set; }
public int? CategoryId { get; set; }
[ForeignKey("CategoryId")]
public Category Category { get; set; }
}
When I try to make a migration I get this error:
The ALTER TABLE statement conflicted with the FOREIGN KEY constraint "FK_Assistants_Categories_CategoryId". The conflict occurred in database "Pirma
isMsSql", table "dbo.Categories", column 'Id'.
I have no idea why.
Thanks
Fix your classes:
public partial class Assistent
{
[Key]
public int Id { get; set; }
public int UserId { get; set; }
public User User{ get; set; }
public DateTime CreatedAtUtc { get; set; }
public int StatusId { get; set; }
public Status Status { get; set; }
public int? CategoryId { get; set; }
[ForeignKey(nameof(CategoryId))]
[InverseProperty("Assistents")]
public virtual Category Category { get; set; }
}
public partial class Category
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public int? ParentId { get; set; }
[ForeignKey(nameof(ParentId))]
[InverseProperty(nameof(Category.InverseParent))]
public virtual Category Parent { get; set; }
[InverseProperty(nameof(Assistent.Category))]
public virtual ICollection<Assistent> Assistents { get; set; }
[InverseProperty(nameof(Category.Parent))]
public virtual ICollection<Category> InverseParent { get; set; }
}
This is db context:
public partial class AssistentsContext : DbContext
{
public AssistentsContext()
{
}
public AssistentsContext(DbContextOptions<AssistentsContext> options)
: base(options)
{
}
public virtual DbSet<Assistent> Assistents { get; set; }
public virtual DbSet<Category> Categories { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Assistent>(entity =>
{
entity.HasOne(d => d.Category)
.WithMany(p => p.Assistents)
.HasForeignKey(d => d.CategoryId);
});
modelBuilder.Entity<Category>(entity =>
{
entity.HasOne(d => d.Parent)
.WithMany(p => p.InverseParent)
.HasForeignKey(d => d.ParentId);
});
OnModelCreatingPartial(modelBuilder);
}
partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
}
Related
I have these entities:
public class Project : Base
{
public string Name { get; set; }
public string Description { get; set; }
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; }
public ProjectStatus CurrentStatus { get; set; } = ProjectStatus.New;
public List<StatusHistory>? StatusHistories { get; set; }
public Team? Team { get; set; }
public int? TeamId { get; set; }
// public ProgressTrackerValue trackerValue { get; set; }
public List<AttachedFile> AttachedFiles { get; set; }
}
public class Task : Base
{
public string Name { get; set; }
public string Description { get; set; }
public DateTime? EstimatedDueDate { get; set; }
public DateTime? ActualDueDate { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; } // ?? End DATE same as ActualDueDate
public TaskStatus CurrentStatus { get; set; } = TaskStatus.Draft;
public int ProjectId { get; set; }
public Project Project { get; set; }
public List<StatusHistory> StatusHistories { get; set; }
public TaskType TaskType { get; set; }
public TaskPriority Priority { get; set; }
public float ? DurationProgress { get; set; }
public List<AttachedFile> AttachedFiles { get; set; }
}
public class Team : Base
{
public string TeamLeaderId { get; set; }
public List<TeamMember>? TeamMembers { get; set; }
public virtual Project Project { get; set; }
}
public class AttachedFile : Base
{
public string OriginalFileName { get; set; }
public string FileName { get; set; }
public string MimeType { get; set; }
public string FileType { get; set; }
public string OwnerType { get; set; }
public int OwnerId {get; set;}
public string FilePath { get; set; }
public long FileSize { get; set; }
}
public class Comment : Base
{
public string Content { get; set; }
public int? ParentCommentId { get; set; }
public List<Comment>? Replies { get; private set; }
public Task Task { get; set; }
public int taskId { get; set; }
public List<AttachedFile>? AttachedFiles { get; set; }
}
public class StatusHistory : Base
{
public string OwnerType { get; set; }
public int OwnerId {get; set;}
public string State { get; set; }
}
public class TaskEmployee : Base
{
public int TaskId { get; set; }
public Task Task { get; set; }
public string EmployeeId { get; set; }
}
public class TeamMember : Base
{
public string UserId { get; set; }
}
What can I do to improve the above entities? Any suggestions.
Also there is UserId,EmployeeId,TeamLeaderId.... all of these supposed to be FK to IdentityUser but this project is isolated from Identity and i can't find a way to link them together. if there is a suggestion on how could I make such relationship in EFCore. (I could make relationship manually but I can't put navigation properties for Identity inside these entities thus not benefiting from EFCore).
Finally there is OwnerType, OwnerId, for example in the AttachedFile entity the attached file could be related to Project, Task, Comment. So I will store the type and id for them in these fields, the problem however that I will not benefit form EF Core functionality this way. For example: I must write SQL manually for every query.
currently the schema look like this:
enter image description here
I have a problem when I want to create my SQL Server database from my EF model.
Here's my model :
public class BilanPatrimonial
{
public int ID { get; set; }
[Key, ForeignKey("EtatCivil")]
public int EtatCivilMonsieurID { get; set; }
public EtatCivil EtatCivilMonsieur { get; set; }
public int EtatCivilMadameID { get; set; }
public EtatCivil EtatCivilMadame { get; set; }
}
public class EtatCivil
{
public int ID { get; set; }
public string Prenoms { get; set; }
public DateTime DateNaissance { get; set; }
public string LieuNaissance { get; set; }
public string Nationalite { get; set; }
public StatutProfessionnel StatutProfessionnel { get; set; }
public string Profession { get; set; }
public string NomEmployeur { get; set; }
public string Activité { get; set; }
public int Ancienneté { get; set; }
public int SalaireAnnuelNet { get; set; }
public int Rentes { get; set; }
public int PensionsNettes { get; set; }
public int BNCBICAnnuellesNetsNMoins1 { get; set; }
public int BNCBICAnnuellesNetsNMoins2 { get; set; }
public bool CentreGestionAgree { get; set; }
public int BeneficeDeficitFoncier { get; set; }
public int DividendesNMoins1 { get; set; }
public int DividendesNMoins2 { get; set; }
}
I have 2 objects of type EtatCivil
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Annonce>().ToTable("Annonces");
modelBuilder.Entity<HonorairesAChargeDe>().ToTable("HonorairesAChargeDe");
modelBuilder.Entity<TypeChauffage>().ToTable("TypesChauffage");
modelBuilder.Entity<TypeCuisine>().ToTable("TypesCuisine");
modelBuilder.Entity<Favori>().ToTable("Favoris");
modelBuilder.Entity<Agenda>().ToTable("Agendas");
modelBuilder.Entity<Evenement>().ToTable("Evenements");
modelBuilder.Entity<Offre>().ToTable("Offres");
modelBuilder.Entity<BilanPatrimonial>().ToTable("BilansPatrimoniaux");
modelBuilder.Entity<EtatCivil>().ToTable("EtatCivils");
//modelBuilder.Entity<ChargesImmobilier>().ToTable("ChargesImmobiliers");
//modelBuilder.Entity<AutresChargesMensuelles>().ToTable("AutresChargesMensuelless");
//modelBuilder.Entity<Placement>().ToTable("Placements");
}
When I try to create the database, the FOREIGN KEY 'FK_BilansPatrimoniaux_EtatCivils_EtatCivilMonsieurID1' cannot be created because of cascading cycles or access.
The message tells me to specify ON DELETE NO ACTION or ON UPDATE NO ACTION but I don't know how to do this.
Any help would be really appreciated, thanks
namespace LoopSquad.Core.Entities.Addresses
{
public class Address
{
public int AddressId { get; set; }
public string NoName { get; set; }
public string AddressL1 { get; set; }
public string AddressL2 { get; set; }
public string Town { get; set; }
public string County { get; set; }
public string Postcode { get; set; }
[ForeignKey("Customer")]
public int CustomerId { get; set; }
public Customers.Customer Customer { get; set; }
public ICollection<Jobs.Job> Jobs { get; set; }
}
}
namespace LoopSquad.Core.Entities.Customers
{
public class Customer
{
[Key]
public int CustomerId { get; set; }
public string CompanyName { get; set; }
[ForeignKey("FKCustomerType")]
public int CustomerTypeId { get; set; }
public CustomerType CustomerType { get; set; }
public ICollection<Addresses.Address> Addresses { get; set; }
}
}
namespace LoopSquad.Core.Entities.Jobs
{
public class Job
{
[Key]
public int JobId { get; set; }
[ForeignKey("FKCustomer")]
public int CustomerId { get; set; }
public Customers.Customer Customer { get; set; }
[ForeignKey("FKAddress")]
public int AddressId { get; set; }
public Addresses.Address Address { get; set; }
public DateTime BookedDateTime { get; set; }
public DateTime CreatedDateTime { get; set; }
[ForeignKey("FKUser")]
public int UserId { get; set; }
public Users.ApplicationUser ApplicationUser { get; set; }
[ForeignKey("FRoomLayout")]
public int RoomLayoutId { get; set; }
public RoomLayout RoomLayout { get; set; }
[ForeignKey("FKJobType")]
public int JobTypeId { get; set; }
public JobType JobType { get; set; }
[ForeignKey("FKLoopType")]
public int loopTypeId { get; set; }
public LoopType LoopType { get; set; }
[ForeignKey("FKJobStatus")]
public int JobStatusId { get; set; }
public JobStatus JobStatus { get; set; }
}
}
I reproduce your problem and it is because you enable cascade delete by default which will result in cycles for your relationships.
Try to disable it using OnDelete(DeleteBehavior.Restrict) in dbcontext, for example
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<Address> Addresses { get; set; }
public DbSet<Customer> Customers { get; set; }
public DbSet<Job> Jobs { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Job>().HasOne(p => p.Customer)
.WithMany()
.HasForeignKey(p => p.CustomerId)
.OnDelete(DeleteBehavior.Restrict);
}
}
Refer to https://learn.microsoft.com/en-us/ef/core/saving/cascade-delete
I have reading and jobOrder class. I want to create a relationship between joborderId in the jobOrder class and jobOrderId in reading class.
public class JobOrder
{
[Key]
public int Id { get; set; }
public int JobOrderId { get; set; }
public DateTime StartDate { get; set; }
public Nullable<DateTime> EndDate { get; set; }
public string MachineCode { get; set; }
public decimal TotalLength { get; set; }
}
public class Reading
{
public int Id { get; set; }
public string MachineCode { get; set; }
public decimal Length { get; set; }
public bool status { get; set; }
public DateTime time { get; set; }
public int JobOrderId { get; set; }
public JobOrder JobOrder { get; set; }
}
The best way is to take a look at the documentation: https://learn.microsoft.com/en-us/ef/core/modeling/relationships#one-to-one
If you do it the way you described then EF will choose one of the entities to be the dependent based on its ability to detect a foreign key property. If the wrong entity is chosen as the dependent, you can use the Fluent API to correct this.
When configuring the relationship with the Fluent API, you use the HasOne and WithOne methods.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Blog>()
.HasOne(p => p.BlogImage)
.WithOne(i => i.Blog)
.HasForeignKey<BlogImage>(b => b.BlogForeignKey);
}
If you follow the code first naming conventions EF will automatically discover the Key, ForeignKey and Navigation properties :
public class JobOrder
{
// Primary key (can be JobOrderId as well)
public int Id { get; set; }
// other fields...
// Foreign key
public int ReadingId { get; set; }
// Navigation property
public Reading Reading { get; set; }
}
public class Reading
{
// Primary key (can be ReadingId as well)
public int Id { get; set; }
// other fields...
// Foreign key
public int JobOrderId { get; set; }
// Navigation property
public JobOrder JobOrder { get; set; }
}
If you have more than one key composite keys to create the relationship, you need to manually define the keys and foreign keys:
public class JobOrder
{
[Key]
[Column(Order=1)]
public int Id { get; set; }
[Key]
[Column(Order=2)]
public int JobOrderNo { get; set; }
// other fields...
// Foreign key
public int ReadingId { get; set; }
// Navigation property
public Reading Reading { get; set; }
}
public class Reading
{
public int Id { get; set; }
// other fields...
[ForeignKey("JobOrder")]
[Column(Order=1)]
public int JobOrderId { get; set; }
[ForeignKey("JobOrder")]
[Column(Order=2)]
public int JobOrderNo { get; set; }
// Navigation property
public JobOrder JobOrder { get; set; }
}
How about going like this, it will create 1 to 1 relationship between JobOrder and Reading
public class JobOrder
{
[Key]
public int Id { get; set; }
public int JobOrderId { get; set; }
public DateTime StartDate { get; set; }
public Nullable<DateTime> EndDate { get; set; }
public string MachineCode { get; set; }
public decimal TotalLength { get; set; }
public virtual Reading Reading { get; set; }
}
public class Reading
{
[Key]
[System.ComponentModel.DataAnnotations.Schema.ForeignKey("JobOrder")]
public int Id { get; set; }
public string MachineCode { get; set; }
public decimal Length { get; set; }
public bool status { get; set; }
public DateTime time { get; set; }
public JobOrder JobOrder { get; set; }
}
I'm getting this error while updating the model I'm sharing my code, please tell me the best solution for this.
Ticket Detail Class:
public class TicketDetail
{
[Key]
public int TicketDetailId { get; set; }
public int GenericOrderId { get; set; }
public int PartId { get; set; }
public int Quantity { get; set; }
public decimal? CustomerPrice { get; set; }
public string Status { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
public virtual Part Part { get; set; }
public virtual Ticket Ticket { get; set; }
}
OrderDetailClass:
public class OrderDetail
{
[Key]
public int OrderDetailId { get; set; }
public int GenericOrderId { get; set; }
public int PartId { get; set; }
public int Quantity { get; set; }
public decimal? UnitPrice { get; set; }
public string Status { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
public virtual Part Part { get; set; }
public virtual Order Order { get; set; }
}
Order Class:
public class Order : GenericOrder
{
public virtual ICollection<OrderDetail> OrderDetails { get; set; }
}
Ticket Class
public class Ticket : GenericOrder
{
public virtual ICollection<TicketDetail> TicketDetails { get; set; }
}
GenericOrderClass:
public abstract class GenericOrder
{
[Key]
public int GenericOrderId { get; set; }
public string ProcessId { get; set; }
public DateTime Date { get; set; }
public string FullName { get; set; }
public string Email { get; set; }
public string Company { get; set; }
public string Phone { get; set; }
public string Message { get; set; }
public decimal Total { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
}
and this is the controller class code
TryUpdateModel(order);
TryUpdateModel(ticket);
try
{
order.Date = DateTime.Now;
ticket.Date = DateTime.Now;
order.ProcessId = DateTime.Now.Ticks.ToString().Substring(12, 6);
ticket.ProcessId = order.ProcessId;
//Add the Order
storeDB.Orders.Add(order);
storeDB.Tickets.Add(ticket);
//Process the order
cart.CreateOrder(order);
cart.CreateTicket(ticket);
// Save all changes
storeDB.SaveChanges();
//return RedirectToAction("Complete",
// new { id = order.QuoteOrderId });
TempData["OrderSuccess"] = "Your order has been submitted successfully with the Process ID " + order.ProcessId;
TempData["OrderId"] = order.GenericOrderId;
TempData["Email"] = order.Email;
return RedirectToAction("Confirm");
}
catch (Exception e)
{
//Invalid - redisplay with errors
ModelState.AddModelError("", e.Message);
return View(order);
}
I have searched internet but couldn't find any solution.
Try saving Order and Ticket and after they are saved add Details to them.