Entity Framework Database Submit - c#

using the following code:
using (GagaShaggyContext db = new GagaShaggyContext())
{
ItemModel itemToChange = null;
itemToChange = (from i in db.Items
where i.ItemID == checkoutItem.Item.ItemID
select i).FirstOrDefault();
itemToChange.FrontFeature = false;
db.SaveChanges();
}
The model is saving back to the database with a brand new ID, which I want to save changes to the original database entry. Is there any reason for this to happen?
Thanks
Edit
On breakpoint analysis adding the receipt item before hand is adding a different ItemID not that I can see why:
using (var db = new GagaShaggyContext())
{
db.Receipts.Add(rec);
db.SaveChanges();
}

using (var db = new GagaShaggyContext())
{
var ItemToUse = (from i in db.ItemModels
where i.ItemModelID == checkoutItem.Item.ItemModelID
select i).FirstOrDefault();
rec.ItemModel = ItemToUse;
db.Receipts.Add(rec);
db.SaveChanges();
}
This fixed it. We need to actually retrieve the relevant Item and put it inside the Receipt (rec) then we could add it, now that Entity Framework recognizes the relationship between these two.

I guess you are trying to Insert into DB
using (GagaShaggyContext db = new GagaShaggyContext())
{
ItemModel itemToChange = new ItemModel();
itemToChange = (from i in db.Items
where i.ItemID == checkoutItem.Item.ItemID
select i).FirstOrDefault();
if(itemToChange !=null)
{
itemToChange.FrontFeature = false;
db .Items.Add(itemToChange);
db.SaveChanges();
}
}
If you are trying to Update the record than
using (GagaShaggyContext db = new GagaShaggyContext())
{
ItemModel itemToChange = new ItemModel();
itemToChange = (from i in db.Items
where i.ItemID == checkoutItem.Item.ItemID
select i).FirstOrDefault();
if(itemToChange !=null)
{
itemToChange.FrontFeature = false;
objDBContext.Entry(itemToChange).State = EntityState.Modified;
objDBContext.SaveChanges();
}
}

Related

Update a record using Entity Framework receiving 2 parameters

I want to update a specific row of the database. This is the code:
public void Update_Datos(int ID)
{
int UserId = Convert.ToInt16((string)(Session["UserId"]));
using (var db = new Entities())
{
//Reading
List<Datos_Personales> objDatos = db.Datos_Personales.ToList<Datos_Personales>();
foreach (Datos_Personales item in objDatos)
{
}
//Update
var datos_personales = db.Datos_Personales.FirstOrDefault(d => d.UserId == UserId && d.Id == ID);
Datos_Personales datos = objDatos[datos_personales.Id];
datos = db.Datos_Personales.Where(d => d.UserId == UserId && d.Id == ID).First();
datos.Fecha_de_nacimiento = Convert.ToDateTime(Fecha_de_nacimiento.Text);
datos.Nombre_Completo = txt_Nombre_Completo.Text;
datos.Identificacion = txt_Identificacion.Text;
datos.Estado_civil = ddEstadoCivil.SelectedValue;
datos.Telefono = txt_num_telefono.Text;
datos.Departamento = ddDepartamento.SelectedValue;
datos.Nacionalidad = Country.SelectedValue;
datos.Salario_min_aceptado = ddSalario_min_aceptado.SelectedValue;
datos.Titulo = txt_Titulo.Text;
datos.Descripcion_Profesional = txt_Descripcion_Profesional.Text;
datos.UserId = Convert.ToInt16(UserId);
db.Datos_Personales.Add(datos);
db.SaveChanges();
}
}
The other is issue is that it creating another row instead updating the one which I need.
You must not read all Db. When you use this line List<Datos_Personales> objDatos = db.Datos_Personales.ToList<Datos_Personales>();, your all entity (all rows in Db) stored into memory.
You can fetch your data directly and edit it. Finally you must not add entity again, only call SaveChages. (If you did not close ChangeTracker)
public void Update_Datos(int ID)
{
int UserId = Convert.ToInt16((string)(Session["UserId"]));
using (var db = new Entities())
{
Datos_Personales datos = db.Datos_Personales.FirstOrDefault(d => d.UserId == UserId && d.Id == ID));
if(datos == null)
return;
datos.Fecha_de_nacimiento = Convert.ToDateTime(Fecha_de_nacimiento.Text);
datos.Nombre_Completo = txt_Nombre_Completo.Text;
datos.Identificacion = txt_Identificacion.Text;
datos.Estado_civil = ddEstadoCivil.SelectedValue;
datos.Telefono = txt_num_telefono.Text;
datos.Departamento = ddDepartamento.SelectedValue;
datos.Nacionalidad = Country.SelectedValue;
datos.Salario_min_aceptado = ddSalario_min_aceptado.SelectedValue;
datos.Titulo = txt_Titulo.Text;
datos.Descripcion_Profesional = txt_Descripcion_Profesional.Text;
datos.UserId = Convert.ToInt16(UserId);
db.SaveChanges();
}
}

Right way to delete a row in ado.net entity data model

I need to delete a row using ado.net entity data model. Already googling about this, but i still can't find out how to do it right.
Here's my code:
else if (mode == 3)
{
LaundryEntities1 db = new LaundryEntities1();
var query = (from user in db.Users
where user.UserID == textBoxID.Text
select user).First();
db.DeleteObject(query);
db.SaveChanges();
reload();
MessageBox.Show("Succesfully delete a user");
clear();
}
You can use
LaundryEntities1 db = new LaundryEntities1();
var query = (from user in db.Users
where user.UserID == textBoxID.Text
select user).First();
db.Entry(employer).State = EntityState.Deleted
if(db.SaveChanges())
MessageBox.Show("Succesfully delete a user");
I make a public class named Session
public class session
{
public static DatabaseEntities db = new DatabaseEntities();
public static User user = null;
}
and changed my code into
Users user = (from x in session.db.Users
where x.UserID == textBoxID.Text
select x).FirstOrDefault();
session.db.Users.DeleteObject(user);
session.db.SaveChanges();

Entity Framework M:1 relationship resulting in primay key duplication

I'm somewhat new to EF 6.0 so I'm pretty sure I'm doing something wrong here.
there are two questions related to the problem
what am I doing wrong here
what's the best practice to achieve this
I'm using a code first model, and used the edmx designer to design the model and relationships, the system needs to pull information periodically from a webservice and save it to a local database (SQL Lite) in a desktop application
so I get an order list from the API, when I populate and try to save Ticket, I get a duplicate key exception when trying to insert TicketSeatType -
how do I insert the ticket to dbContext, so that It doesn't try and re-insert insert TicketSeatType and TicketPriceType, I have tried setting the child object states to unchanged but it seems to be inserting
secondly, what would be the best practice to achieve this using EF ? it just looks very inefficient loading each object into memory and comparing if it exists or not
since I need to update the listing periodically, I have to check against each object in the database if it exists, then update, else insert
code:
//read session from db
if (logger.IsDebugEnabled) logger.Debug("reading session from db");
dbSession = dbContext.SessionSet.Where(x => x.Id == sessionId).FirstOrDefault();
//populate orders
List<Order> orders = (from e in ordersList
select new Order {
Id = e.OrderId,
CallCentreNotes = e.CallCentreNotes,
DoorEntryCount = e.DoorEntryCount,
DoorEntryTime = e.DoorEntryTime,
OrderDate = e.OrderDate,
SpecialInstructions = e.SpecialInstructions,
TotalValue = e.TotalValue,
//populate parent refernece
Session = dbSession
}).ToList();
//check and save order
foreach (var o in orders) {
dbOrder = dbContext.OrderSet.Where(x => x.Id == o.Id).FirstOrDefault();
if (dbOrder != null) {
dbContext.Entry(dbOrder).CurrentValues.SetValues(o);
dbContext.Entry(dbOrder).State = EntityState.Modified;
}
else {
dbContext.OrderSet.Add(o);
dbContext.Entry(o.Session).State = EntityState.Unchanged;
}
}
dbContext.SaveChanges();
//check and add ticket seat type
foreach (var o in ordersList) {
foreach (var t in o.Tickets) {
var ticketSeatType = new TicketSeatType {
Id = t.TicketSeatType.TicketSeatTypeId,
Description = t.TicketSeatType.Description
};
dbTicketSeatType = dbContext.TicketSeatTypeSet.Where(x => x.Id == ticketSeatType.Id).FirstOrDefault();
if (dbTicketSeatType != null) {
dbContext.Entry(dbTicketSeatType).CurrentValues.SetValues(ticketSeatType);
dbContext.Entry(dbTicketSeatType).State = EntityState.Modified;
}
else {
if (!dbContext.ChangeTracker.Entries<TicketSeatType>().Any(x => x.Entity.Id == ticketSeatType.Id)) {
dbContext.TicketSeatTypeSet.Add(ticketSeatType);
}
}
}
}
dbContext.SaveChanges();
//check and add ticket price type
foreach (var o in ordersList) {
foreach (var t in o.Tickets) {
var ticketPriceType = new TicketPriceType {
Id = t.TicketPriceType.TicketPriceTypeId,
SeatCount = t.TicketPriceType.SeatCount,
Description = t.TicketPriceType.Description
};
dbTicketPriceType = dbContext.TicketPriceTypeSet.Where(x => x.Id == ticketPriceType.Id).FirstOrDefault();
if (dbTicketPriceType != null) {
dbContext.Entry(dbTicketPriceType).CurrentValues.SetValues(ticketPriceType);
dbContext.Entry(dbTicketPriceType).State = EntityState.Modified;
}
else {
if (!dbContext.ChangeTracker.Entries<TicketPriceType>().Any(x => x.Entity.Id == ticketPriceType.Id)) {
dbContext.TicketPriceTypeSet.Add(ticketPriceType);
}
}
}
}
dbContext.SaveChanges();
//check and add tickets
foreach (var o in ordersList) {
dbOrder = dbContext.OrderSet.Where(x => x.Id == o.OrderId).FirstOrDefault();
foreach (var t in o.Tickets) {
var ticket = new Ticket {
Id = t.TicketId,
Quantity = t.Quantity,
TicketPrice = t.TicketPrice,
TicketPriceType = new TicketPriceType {
Id = t.TicketPriceType.TicketPriceTypeId,
Description = t.TicketPriceType.Description,
SeatCount = t.TicketPriceType.SeatCount,
},
TicketSeatType = new TicketSeatType {
Id = t.TicketSeatType.TicketSeatTypeId,
Description = t.TicketSeatType.Description
},
Order = dbOrder
};
//check from db
dbTicket = dbContext.TicketSet.Where(x => x.Id == t.TicketId).FirstOrDefault();
dbTicketSeatType = dbContext.TicketSeatTypeSet.Where(x => x.Id == t.TicketSeatType.TicketSeatTypeId).FirstOrDefault();
dbTicketPriceType = dbContext.TicketPriceTypeSet.Where(x => x.Id == t.TicketPriceType.TicketPriceTypeId).FirstOrDefault();
if (dbTicket != null) {
dbContext.Entry(dbTicket).CurrentValues.SetValues(t);
dbContext.Entry(dbTicket).State = EntityState.Modified;
dbContext.Entry(dbTicket.Order).State = EntityState.Unchanged;
dbContext.Entry(dbTicketSeatType).State = EntityState.Unchanged;
dbContext.Entry(dbTicketPriceType).State = EntityState.Unchanged;
}
else {
dbContext.TicketSet.Add(ticket);
dbContext.Entry(ticket.Order).State = EntityState.Unchanged;
dbContext.Entry(ticket.TicketSeatType).State = EntityState.Unchanged;
dbContext.Entry(ticket.TicketPriceType).State = EntityState.Unchanged;
}
}
}
dbContext.SaveChanges();
UPDATE:
Found the answer, it has to do with how EF tracks references to objects, in the above code, I was creating new entity types from the list for TicketPriceType and TicketSeatType:
foreach (var o in ordersList) {
dbOrder = dbContext.OrderSet.Where(x => x.Id == o.OrderId).FirstOrDefault();
foreach (var t in o.Tickets) {
var ticket = new Ticket {
Id = t.TicketId,
Quantity = t.Quantity,
TicketPrice = t.TicketPrice,
TicketPriceType = new TicketPriceType {
Id = t.TicketPriceType.TicketPriceTypeId,
Description = t.TicketPriceType.Description,
SeatCount = t.TicketPriceType.SeatCount,
},
TicketSeatType = new TicketSeatType {
Id = t.TicketSeatType.TicketSeatTypeId,
Description = t.TicketSeatType.Description
},
Order = dbOrder
};
....
in this case the EF wouldn't know which objects they were and try to insert them.
the solution is to read the entities from database and allocate those, so it's referencing the same entities and doesn't add new ones
foreach (var t in o.Tickets) {
//check from db
dbTicket = dbContext.TicketSet.Where(x => x.Id == t.TicketId).FirstOrDefault();
dbTicketSeatType = dbContext.TicketSeatTypeSet.Where(x => x.Id == t.TicketSeatType.TicketSeatTypeId).FirstOrDefault();
dbTicketPriceType = dbContext.TicketPriceTypeSet.Where(x => x.Id == t.TicketPriceType.TicketPriceTypeId).FirstOrDefault();
var ticket = new Ticket {
Id = t.TicketId,
Quantity = t.Quantity,
TicketPrice = t.TicketPrice,
TicketPriceType = dbTicketPriceType,
TicketSeatType = dbTicketSeatType,
Order = dbOrder
};
...}
Don't you think that you are trying to write very similar codes for defining the state of each entity?
We can handle all of these operations with a single command.
You can easily achieve this with the newly released EntityGraphOperations for Entity Framework Code First. I am the author of this product. And I have published it in the github, code-project (includes a step-by-step demonstration and a sample project is ready for downloading) and nuget. With the help of InsertOrUpdateGraph method, it will automatically set your entities as Added or Modified. And with the help of DeleteMissingEntities method, you can delete those entities which exists in the database, but not in the current collection.
// This will set the state of the main entity and all of it's navigational
// properties as `Added` or `Modified`.
context.InsertOrUpdateGraph(ticket);
By the way, I feel the need to mention that this wouldn't be the most efficient way of course. The general idea is to get the desired entity from the database and define the state of the entity. It would be as efficient as possible.

Update whole object with Linq or must I bind each property?

I currently have this method which updates my university object and then saves the changes.
public static int Update(Models.University uni)
{
using (var ctx = new ApplicationDbContext())
{
var x = (from y in ctx.Universities
where y.Id == uni.Id
select y).FirstOrDefault();
x.PrincipleName = uni.PrincipleName;
return ctx.SaveChanges();
}
}
Is there a way to save the whole object instead of setting each property?
For example something like(I tried this but the update fails):
public static int Update(Models.University uni)
{
using (var ctx = new ApplicationDbContext())
{
var x = (from y in ctx.Universities
where y.Id == uni.Id
select y).FirstOrDefault();
x = uni;
return ctx.SaveChanges();
}
}
If uni is also an entity then you can just attach it to context
ctx.Universities.Attach(uni);
// set the state of the entity to modified so changes are saved
ctx.Entry(uni).State = EntityState.Modified;
ctx.SaveChanges();

Delete Many to Many relationship using Entity Framework

I've three tables Student (studID, fullName, gender...), Enroll (studID, courseID, date) and Course (courseID,courseName, ...). I used the code below to delete all records from Enroll table with studID 001 where there are about three courses the student signed for. However, it only deletes one record.
using(var context = new DBEntities())
{
var _stud = (from s in context.Students where s.studID == "001" select s).FirstOrDefault();
var _course = _stud.Courses.FirstOrDefault();
_course.Students.Remove(_stud);
context.SaveChanges();
}
What do I miss here?
Thank you guys for assisting. Here is how I solved it:
using (var context = new DBEntities())
{
var student = (from s in context.Students where s.studID == "001" select s).FirstOrDefault<Student>();
foreach (Course c in student.Courses.ToList())
{
student.Courses.Remove(c);
}
context.SaveChanges();
}
I used the code below to delete all records from Enroll table
Are you deleting enrolls or students?
Student student = context.Student.FirstOrDefault(s => s.studID == "001");
if (student!=null)
{
student.Enrolls.Load();
student.Enrolls.ToList().ForEach(e => context.Enroll.DeleteObject(e));
}
Have you try this code :
var student = context.Students.Where(p => p.studID == "001").ToList();
foreach (var item in student)
{
if (student != null)
{
var course = student.Courses.ToList();
if (course != null)
{
foreach (var item2 in course)
{
course.Students.Remove(item2);
context.SaveChanges();
}
}
}
}
For others looking to this answer you could also do it using include.
using(var context = new DBEntities())
{
// Get student by id
var student = context.Students.Include(s => s.Courses).Where(s => s.studID == "001").FirstOrDefault();
if(student.Courses != null)
{
// Retrieve list of courses for that student
var coursesToRemove = stud.Courses.ToList();
// Remove courses
foreach (var course in coursesToRemove)
{
student.Courses.Remove(course);
}
// Save changes
context.SaveChanges();
}
}

Categories

Resources