Reputation: 326
I'm trying to come up with a car service booking application that allows one to either book a car into a service as well as buy a few parts, which is not essential, but I get an error that reads as follows:
SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.BasketLines_dbo.Parts_PartID". The conflict occurred in database "aspnet-Noir-20190224082924", table "dbo.Parts", column 'PartId'. The statement has been terminated.
My classes are as follows:
PART
public class Part
{
[Key]
public int PartId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public byte[] ImageFile { get; set; }
public string ImageFilePath { get; set; }
public decimal Price { get; set; }
public virtual ICollection<ServicePartMapping>
ServicePartMappings { get; set;}
}
Service
public class Service
{
public int ServiceId { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public decimal Price { get; set; }
public ICollection<Part> Parts { get; set; }
}
ServicePartMapping
public class ServicePartMapping
{
public int ServicePartMappingID { get; set; }
public int PartNumber { get; set; }
public int? ServiceId { get; set; }
public int? ServicePartId { get; set; }
public virtual Service Service { get; set; }
public virtual ServicePart ServicePart { get;
set; }
}
Basket
public class Basket
{
public int Id { get; set; }
private string BasketID { get; set; }
private const string BasketSessionKey =
"BasketID";
private ApplicationDbContext db = new
ApplicationDbContext();
private string GetBasketID()
{
if
(HttpContext.Current.Session[BasketSessionKey]
== null)
{
if
(!string.IsNullOrWhiteSpace
(HttpContext.Current
.User.Identity.Name))
{
HttpContext.Current
.Session[BasketSessionKey] =
HttpContext.Current
.User.Identity.Name;
}
else
{
Guid tempBasketID = Guid.NewGuid()
HttpContext.Current
.Session[BasketSessionKey]
= tempBasketID.ToString();
}
}
return
HttpContext.Current
.Session[BasketSessionKey].ToString();
}
public static Basket GetBasket()
{
Basket basket = new Basket();
basket.BasketID = basket.GetBasketID();
return basket;
}
public void AddServiceToBasket(int serviceID,
int quantity)
{
var basketLine =
db.BasketLines.FirstOrDefault(b =>
b.BasketID == BasketID && b.ServiceID
== serviceID);
if (basketLine == null)
{
basketLine = new BasketLine
{
ServiceID = serviceID,
BasketID = BasketID,
Quantity = quantity,
DateCreated = DateTime.Now
};
db.BasketLines.Add(basketLine);
}
else
{
basketLine.Quantity += quantity;
}
db.SaveChanges();
}
public void AddPartToBasket(int partID, int
quantity)
{
var basketLine =
db.BasketLines.FirstOrDefault(b =>
b.BasketID == BasketID && b.PartId
== partID);
if (basketLine == null)
{
basketLine = new BasketLine
{
PartId = partID,
BasketID = BasketID,
Quantity = quantity,
DateCreated = DateTime.Now
};
db.BasketLines.Add(basketLine);
}
else
{
basketLine.Quantity += quantity;
}
db.SaveChanges();
}
public void RemoveLine(int ID)
{
var basketLine = db.BasketLines.FirstOrDefault(b => b.BasketID == BasketID && b.ServiceID
== ID || b.PartId == ID);
if (basketLine != null)
{
db.BasketLines.Remove(basketLine);
}
db.SaveChanges();
}
public void UpdateBasket(List<BasketLine> lines)
{
foreach (var line in lines)
{
var basketLine = db.BasketLines.FirstOrDefault(b => b.BasketID == BasketID &&
b.ServiceID == line.ServiceID);
if (basketLine != null)
{
if (line.Quantity == 0)
{
RemoveLine(line.ServiceID);
}
else
{
basketLine.Quantity = line.Quantity;
}
}
}
db.SaveChanges();
}
public void EmptyBasket()
{
var basketLines = db.BasketLines.Where(b => b.BasketID == BasketID);
foreach (var basketLine in basketLines)
{
db.BasketLines.Remove(basketLine);
}
db.SaveChanges();
}
public List<BasketLine> GetBasketLines()
{
return db.BasketLines.Where(b => b.BasketID == BasketID).ToList();
}
public decimal GetTotalCost()
{
decimal basketTotal = decimal.Zero;
decimal serviceTotal = decimal.Zero;
decimal partTotal = decimal.Zero;
if (GetBasketLines().Count > 0)
{
serviceTotal = db.BasketLines.Where(b => b.BasketID == BasketID).Sum(b => b.Service.Price
* b.Quantity);
partTotal = db.BasketLines.Where(b => b.BasketID == BasketID).Sum(b => b.Part.Price
* b.Quantity);
basketTotal = serviceTotal + partTotal;
}
return basketTotal;
}
public int GetNumberOfItems()
{
int numberOfItems = 0;
if (GetBasketLines().Count > 0)
{
numberOfItems = db.BasketLines.Where(b => b.BasketID == BasketID).Sum(b => b.Quantity);
}
return numberOfItems;
}
public void MigrateBasket(string userName)
{
//find the current basket and store it in memory using ToList()
var basket = db.BasketLines.Where(b => b.BasketID == BasketID).ToList();
//find if the user already has a basket or not and store it in memory using ToList()
var usersBasket = db.BasketLines.Where(b => b.BasketID == userName).ToList();
//if the user has a basket then add the current items to it
if (usersBasket != null)
{
//set the basketID to the username
string prevID = BasketID;
BasketID = userName;
//add the lines in anonymous basket to the user's basket
foreach (var line in basket)
{
AddServiceToBasket(line.ServiceID, line.Quantity);
AddPartToBasket(line.PartId, line.Quantity);
}
//delete the lines in the anonymous basket from the database
BasketID = prevID;
EmptyBasket();
}
else
{
//if the user does not have a basket then just migrate this one
foreach (var basketLine in basket)
{
basketLine.BasketID = userName;
}
db.SaveChanges();
}
HttpContext.Current.Session[BasketSessionKey] = userName;
}
public decimal CreateOrderLines(int orderID)
{
decimal orderTotal = 0;
var basketLines = GetBasketLines();
foreach (var item in basketLines)
{
BillLine BillLine = new BillLine
{
Service = item.Service,
ServiceID = item.ServiceID,
ServiceName = item.Service.Name,
Quantity = item.Quantity,
ServicePrice = item.Service.Price,
BillID = orderID
};
orderTotal += (item.Quantity * item.Service.Price);
db.BillLines.Add(BillLine);
}
db.SaveChanges();
EmptyBasket();
return orderTotal;
}
}
BasketLine
public class BasketLine
{
public int ID { get; set; }
public string BasketID { get; set; }
public int ServiceID { get; set; }
public int PartId { get; set; }
[Range(0, 50, ErrorMessage = "Please enter a quantity between 0 and 50")]
public int Quantity { get; set; }
public DateTime DateCreated { get; set; }
public virtual Service Service { get; set; }
public virtual Part Part { get; set; }
}
Upvotes: 0
Views: 106
Reputation: 24957
Assumed that EF Code First is used, the exception message indicates that you're using foreign key constraint inside BasketLines
table which references PartId
primary key column in Parts
table, and you're trying to insert a value into BasketLines.PartId
column which not exist in Parts
table at this statement:
basketLine = new BasketLine
{
PartId = partID, // this assignment is the problem source
BasketID = BasketID,
Quantity = quantity,
DateCreated = DateTime.Now
};
db.BasketLines.Add(basketLine);
Based from inspection, you're trying to build relationship between Service
, Part
and BasketLine
entities, therefore I suggested to add ForeignKeyAttribute
for ServiceId
and PartId
property in BasketLine
entity:
public class BasketLine
{
public int ID { get; set; }
public string BasketID { get; set; }
[ForeignKey("Service")]
public int ServiceID { get; set; }
[ForeignKey("Part")]
public int PartId { get; set; }
[Range(0, 50, ErrorMessage = "Please enter a quantity between 0 and 50")]
public int Quantity { get; set; }
public DateTime DateCreated { get; set; }
public virtual Service Service { get; set; }
public virtual Part Part { get; set; }
}
Additionally, since it's stated that a BasketLine
requires Service
with optional Part
, you may also try modify OnModelCreating()
method inside DbContext
like this:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<BasketLine>()
.HasOptional(x => x.Part) // can save BasketLine without specifying Part
.WithRequired(x => x.Service); // cannot save BasketLine without using Service
}
Related issues:
Configure One-to-One Relationships in EF Code First
The INSERT statement conflicted with the FOREIGN KEY constraint
Upvotes: 1