MVC3 db.SaveChanges() INSERT statement error - asp.net-mvc-3

I am following MVC music store similarly. http://www.asp.net/mvc/tutorials/mvc-music-store/mvc-music-store-part-9
When I doing create orderDetails, I have got error with inner exception.
Could you help me what does it mean?
"The INSERT statement conflicted with the FOREIGN KEY constraint \"FK_OrderDetails_Product\". The conflict occurred in database \"rentalDB\", table \"dbo.Product\", column 'productId'.\r\nThe statement has been terminated."
Do I need to check in SQL Server? I don't know why it errors happen..
Can you give me some advice? I am giving you some my code.
Please help me. Thanks.
public int CreateOrder(Order order)
{
decimal orderTotal = 0;
var cartItems = GetCartItems();
// Iterate over the items in the cart, adding the order details for each
foreach (var item in cartItems)
{
var orderDetail = new OrderDetails
{
productId = item.Product.productId,
orderId = order.orderId,
unitPrice = item.priceValue,
rentalPeriod = item.rentalPeriod,
startDate = item.dateCreated.AddDays(2),
endDate = item.dateCreated.AddDays(2 + item.rentalPeriod),
quantity = item.count
};
// Set the order total of the shopping cart
orderTotal += (item.count * item.priceValue);
db.OrderDetails.Add(orderDetail);
}
// Set the order's total to the orderTotal count
order.total = orderTotal;
// Save the order
db.SaveChanges(); //I have error in here!!!
// Empty the shopping cart
EmptyCart();
// Return the OrderId as the confirmation number
return order.orderId;
}
Here is viewModel
public class ShoppingCartViewModel
{
public List<Cart> CartItems { get; set; }
public decimal CartTotal { get; set; }
}
Here is Cart
public class Cart
{
[Key]
public int recordId { get; set; }
public string cartId { get; set; }
public int productId { get; set; }
public decimal priceValue { get; set; }
public int count { get; set; }
public int rentalPeriod { get; set; }
public DateTime dateCreated { get; set; }
public virtual Product Product { get; set; }
}
Here is Product
public class Product
{
[Key] public int productId { get; set; }
[Required(ErrorMessage = "Please select category")]
public int categoryId { get; set; }
[Required(ErrorMessage = "Please fill in model name")]
[DisplayName("Model name")]
public String model { get; set; }
[DisplayName("Description")]
public String description { get; set; }
[DisplayName("Original price")]
public decimal price { get; set; }
[Required(ErrorMessage = "Please fill in stock of product")]
[DisplayName("Stock")]
public int stock { get; set; }
public virtual Category Category { get; set; }
}

I did not set FK in OrderDetails..
That's what I have got error before.
When I create FK between OrderDetails and Order, it will work.

Related

I cannot add the orders to the database

I am building an e-store with ASP.NET Core. I've created CRUD operations to add my products and save it to the database, it is working fine. Then I wanted to save the orders from the customers to my database, sadly I couldn't manage to do so.
When I click a button, it saves the order to the database and sends the customer to the thank you page.
Can you please check my code and tell me where am going wrong.
This is my OrderController:
[HttpPost]
public async Task<IActionResult> PlaceOrder([FromBody] Order model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var order = new Order
{
OrderDate = DateTime.Now,
Name = model.Name,
Address = model.Address,
Email = model.Email,
PhoneNo = model.PhoneNo
};
var orderDetails = new List<OrderDetails>();
foreach (var item in model.OrderDetails)
{
orderDetails.Add(new OrderDetails
{
ProductId = item.ProductId,
// Quantity = item.Quantity,
// Price = item.Price,
Order = order
});
}
using (var context = new AppDbContext(_dbContextOptions))
{
context.Order.Add(order);
context.OrderDetails.AddRange(orderDetails);
await context.SaveChangesAsync();
}
// returns a HTTP 200 OK response to the client indicating that the operation was successful.
return Ok();
}
and this is the button from my view:
<p>
<a asp-controller="Order" asp-action="PlaceOrder" class="btn btn-primary addToCart">Place my order</a>
</p>
Order class:
public class Order
{
public Order()
{
OrderDetails = new List<OrderDetails>();
}
public int Id { get; set; }
[Display(Name = "Order No")]
public string OrderNo { get; set; }
[Required]
public string Name { get; set; }
[Required]
[Display(Name = "Phone Number")]
public string PhoneNo { get; set; }
[Required]
[EmailAddress]
public string Email { get; set; }
[Required]
public string Address { get; set; }
[Display(Name = "Today's Date")]
public DateTime OrderDate { get; set; }
public virtual List<OrderDetails> OrderDetails { get; set; }
}
Order details class
public class OrderDetails
{
public int Id { get; set; }
[Display(Name = "Order")]
public int OrderId { get; set; }
[Display(Name = "Product")]
public int ProductId { get; set; }
[ForeignKey("OrderId")]
public Order Order { get; set; }
[ForeignKey("PorductId")]
public Product Product { get; set; }
}

How to group by on first table row many to many relation with left join in LINQ

How can I group by complaint in this scenario?
I get all Data with left join with bellow query
now I want all the application users grouped for every related complaint row
my mean one complaint should have many users that is assigned to how should I group users by
complaint and how to loop through it in order to assign the grouped users to any ViewModel
property
public class Complaint
{
[Key]
public int Id { get; set; }
[Required]
public string? Name { get; set; }
[Required]
public string? Email { get; set; }
[Required]
public string? Complaint{ get; set; }
public ICollection<AsignComplaintToUsers> asignComplaintToUsers { get; set; }
}
public class ApplicationUser : IdentityUser
{
[Column(TypeName = "nvarchar(100)")]
public string? FirstName { get; set; }
[PersonalData]
[Column(TypeName = "nvarchar(100)")]
public string? LastName { get; set; }
public ICollection<AsignComplaintToUsers> asignComplaintToUsers { get; set; }
}
public class AsignComplaintToUsers
{
[System.ComponentModel.DataAnnotations.Key]
public int Id { get; set; }
public int ComplaintId { get; set; }
[ForeignKey("ComplaintId")]
public Complaint complaint { get; set; }
public string? AsignToId { get; set; }
[ForeignKey("AsignTo")]
public ApplicationUser applicationUser { get; set; }
public string? AsignById { get; set; }
}
var xyz =
(from c in _context.complaints
join AC in _context.asignComplaintToUsers
on c.Id equals AC.ComplaintId into temp
from t in temp.DefaultIfEmpty()
join AppUser in _context.applicationUsers
on t.AsignTo equals AppUser.Id into temp2
from t2 in temp2.DefaultIfEmpty()
select new
{
complaint = c,
asugnSugessionTousers = t,
usersWhoAsignedComplaints = t2
})
.ToList();
Now I want to have list of all user assigned to each complaint, so how can I do that please?

need to convert sql query to linq and return list of records

Hai using sql query its working database side, directly did not database because it code first approach. so i need following sql query convert to linq query. please any one suggest me .
SELECT Sy.SystemUserName,
MIN(Sc.CreatedOn) as StartedTime,
MAX(Sc.CreatedOn) as ExitTime,
datediff(MINUTE,
MIN(Sc.CreatedOn) ,
MAX(Sc.CreatedOn)) as WorkingHours
from SystemDetails Sy
LEFT JOIN Screenshots Sc on Sy.id = Sc.SystemId
where Sy.CompanyGUID = '25'
AND Sy.IsDeleted = 0
and (datediff(dd,Sc.CreatedOn,getdate()) = 0
Or SC.CreatedOn IS NULL)
GROUP By Sy.SystemUserName
SystemDetails Model :
public class SystemDetails
{
public int Id { get; set; }
[Required]
public string GuidID { get; set; }
[Required]
public string SystemUserName { get; set; }
[Required]
public string CompanyGUID { get; set; }
[Required]
public int TeamId { get; set; }
public User User { get; set; }
public ICollection<Screenshot> Screenshot { get; set; }
}
Screenshot Model :
public class Screenshot
{
public int Id { get; set; }
[Required]
public string GuidId { get; set; }
[Required]
public int SystemId { get; set; }
[Required]
public string Screenshotname { get; set; }
public DateTime CreatedOn { get; set; }
public string CreatedBy { get; set; }
public SystemDetails System { get; set; }
}
Return collection Class :
public class UserAttendance
{
public string StaffName { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public string WorkingHours { get; set; }
}
Here SystemDetails table Systemusername and Screenshot table CreatedOn fields we needed, SystemDeatils Id field and Screenshot SystemId field are key constraint. Need to get SystemUserName and Minimum CreatedOn date as StartTime, Maximum CreatedOn Date as EndTime. we get both datetime duration as WorkingHours. we have get all values using ef core. Incase CreatedOn date null or no date avilable then return '1900-01-01' default date. Please suggest me
Try this query:
var query =
from sy in dbContext.SystemDetails
from sc in sy.Screenshot
where sy.CompanyGUID == "25" && !sy.IsDeleted
&& (sc.CreatedOn == null || EF.Functions.DateDiffDay(sc.CreatedOn.Value, DateTime.Now) == 0)
group sc by new { sc.SystemUserName } into g
select new UserAttendance
{
StaffName = g.Key.SystemUserName,
StartTime = g.Min(x => x.CreatedOn.Value),
EndTime = g.Max(x => x.CreatedOn.Value),
WorkingHours = EF.Functions.DateDiffMinute(g.Min(x => x.CreatedOn.Value), g.Max(x => x.CreatedOn.Value)).ToString()
};

EF LINQ Query for selecting multiple table in single row and count

I have two tables with data for veterinary medicine.
Customers have many patients(pats), relation is "one to many".
I want to show customers with their petsname and count single line
Table: Customer
public class Customer
{
[Key]
public int ID { get; set; }
public bool IsActive { get; set; }
public string TC { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string Email { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public string Note { get; set; }
public int AccountID { get; set; }
}
Table: Patient (Pet)
public class Patient
{
[Key]
public int PatientID { get; set; }
public bool IsActive { get; set; }
public int TypePatientID { get; set; }
public string TypeRace { get; set; }
public string CIPCode { get; set; }
public string Color { get; set; }
public string PatientName { get; set; }
public int Status { get; set; }
public int GenderID { get; set; }
public DateTime BirthDate { get; set; }
public DateTime? DeathDate { get; set; }
public int CustomerID { get; set; }
public int AccountID { get; set; }
}
public class CustomerPageModel
{
[Key]
public int ID { get; set; }
public bool IsActive { get; set; }
public string TC { get; set; }
public string Name { get; set; }
public string Surname { get; set; }
public string Email { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public string Note { get; set; }
public int AccountID { get; set; }
public string Pats { get; set; }
public int PatCount { get; set; }
}
I tried the following code:
var result = from p in context.Customers
join f in context.Patients on p.ID equals f.CustomerID
where p.AccountID == AccountID
group f by new { f.CustomerID, p.IsActive, p.TC, p.Name, p.Surname, p.Email, p.Address, p.Phone, p.Note, p.AccountID, f.PatientName,p.ID } into g
select new CustomerPageModel
{
ID=g.Key.ID,
IsActive = g.Key.IsActive,
TC = g.Key.TC,
Name = g.Key.Name,
Surname = g.Key.Surname,
Email = g.Key.Email,
Address = g.Key.Address,
Phone = g.Key.Phone,
Note = g.Key.Note,
AccountID = g.Key.AccountID,
Pats = string.Join(",", g.Select(x => x.PatientName))
};
Expected Result is:
[
{
"id":13,
"isActive":true,
"tc":"1234",
"name":"John ",
"surname":"Snow",
"email":"",
"address":"",
"phone":"",
"note":null,
"accountID":3,
"pats":"Oscar,Puffy",
"patCount":2
},
{
"id":14,
"isActive":true,
"tc":"2345",
"name":"Mark",
"surname":"Zurk",
"email":"",
"address":"",
"phone":"",
"note":null,
"accountID":3,
"pats":"Mars",
"patCount":1
}
]
Please check link:
https://dotnetfiddle.net/rsv45D
Can anyone help me to write this ef query?
Why Group by all the fields, as you just want to group by user that should be CustomerID (or whatever its key field is):
var result = from p in customers
join f in patients on p.ID equals f.CustomerID
where p.AccountID == AccountID
group new { f, p } by f.CustomerID into g
select new CustomerPageModel
{
ID = g.Key,
IsActive = g.First().p.IsActive,
TC = g.First().p.TC,
Name = g.First().p.Name,
Surname = g.First().p.Surname,
Email = g.First().p.Email,
Address = g.First().p.Address,
Phone = g.First().p.Phone,
Note = g.First().p.Note,
AccountID = g.First().f.AccountID,
Pats = string.Join(",", g.Select(x => x.f.PatientName)),
PatCount = g.Count()
};
Demo Link

Count total based on a foreign key value using LINQ

I'm trying to do something like the following done in SQL
SELECT COUNT(*) AS "Total"
FROM dbo.Items
WHERE CategoryID IN (SELECT CategoryID
FROM Categories
WHERE Name = 'Beverages')
Any ideas how we accomplish this in LINQ?
*Update
Item class code:
public class Item
{
[Key]
public int ItemID { get; set; }
public virtual Category Category { get; set; }
public virtual Brand Brand { get; set; }
public int CategoryID { get; set; }
public int BrandID { get; set; }
[Display(Name ="Product Name")]
[Required(ErrorMessage = "Product name is required")]
public string ItemName { get; set; }
[Display(Name="Product Price")]
public decimal? ItemPrice { get; set; }
[DataType(DataType.ImageUrl)]
[Display(Name = "Image URL")]
public string ImageUrl { get; set; }
}
Category class code:
public class Category
{
public int CategoryID { get; set; }
[DisplayName("Category Name")]
public virtual string Name { get; set; }
public virtual List<Item> Items { get; set; }
}
Update
Models
public class Item
{
[Key]
public int ItemID { get; set; }
public Category Category { get; set; }
public int CategoryID { get; set; }
public int BrandID { get; set; }
[Display(Name = "Product Name")]
[Required(ErrorMessage = "Product name is required")]
public string ItemName { get; set; }
[Display(Name = "Product Price")]
public decimal? ItemPrice { get; set; }
[DataType(DataType.ImageUrl)]
[Display(Name = "Image URL")]
public string ImageUrl { get; set; }
}
public class Category
{
[Key]
public int CategoryID { get; set; }
public virtual string Name { get; set; }
public virtual List<Item> Items { get; set; }
}
Sample of data used
You want item's where category = Beverages
You can make it from items end
var itemsCount1 = dbcontext
.Items
.Count(x => x.Category.Name == "Beverages");
You can make it from categories end
//if there is no Category with the name Beverages return 0
var itemsCount2 = dbcontext
.Categories
.FirstOrDefault(x => x.Name == "Beverages")?.Items?.Count() ?? 0;
Query Result
You could get Count with following.
var results = Categories.Where(x=>x.Name.Equals("Beverages")
.Join(Items,
c=>c.CategoryID,
i=>i.CategoryID,
(c,i)=> i).Count();
For mock data,
var Categories = new List<Category>
{
new Category{CategoryID =1, Name ="Beverages"},
new Category{CategoryID =2, Name ="One"},
new Category{CategoryID =3, Name ="Two"}
};
var Items = new List<Item>
{
new Item{ItemID=3,CategoryID=4,ItemName="abc1"},
new Item{ItemID=1,CategoryID=1,ItemName="abc2"},
new Item{ItemID=1,CategoryID=1,ItemName="abc3"},
new Item{ItemID=1,CategoryID=1,ItemName="abc4"},
new Item{ItemID=1,CategoryID=1,ItemName="abc5"},
new Item{ItemID=2,CategoryID=1,ItemName="abc6"},
new Item{ItemID=3,CategoryID=4,ItemName="abc7"},
new Item{ItemID=4,CategoryID=2,ItemName="abc8"},
};
Output : 5
Update
var results = dbContext.Categories.Where(x=>x.Name.Equals("Beverages")
.Join(dbContext.Items,
c=>c.CategoryID,
i=>i.CategoryID,
(c,i)=> i).Count();

Resources