I am trying to pass 'the name of the person who modified the record. I got that on my addedBy variable but not sure how to pass it to the context.tableName.column name.
using (var context = new MyEntities())
{
var result = context.MyTableName.Where(x => x._ID == paramId).FirstOrDefault();
if (result != null)
{
var addedBy = User.Identity.Name;
context.MyTableName.Add(addedBy);
context.MyTableName.Remove(result);
context.SaveChanges();
}
return Json(new
{
data = result,
JsonRequestBehavior.AllowGet
});
}
Remove your Remove() call, and set the AddedBy property:
result.AddedBy = addedBy;
Then call SaveChanges().
Related
So, I'm trying to update rows where LOGIN IS NULL and ID = 1. If there are no rows with these parameters then add new row. I use attach to make that in 1-2 queries so I'm trying to avoid SELECT first and then update.
Problem in NULL value. EF simply ignores LOGIN since it has null value, however I need to find only rows where LOGIN IS NULL. Can I solve that problem without additional SELECT query?
My code:
using (var db = new EntityContext())
{
var ent = new Entity { ID = 1, LOGIN = null };
db.Entities.Attach(ent);
ent.LOGIN = "Whatever";
ent.EMAIL = "Whatever";
int count = db.SaveChanges();
if (count == 0)
{
var clone_ent = new Entity { LOGIN = "Whatever", PASS = "Whatever" };
db.Entities.Add(clone_ent);
db.SaveChanges();
}
}
SQL analog:
UPDATE Entities SET LOGIN = #LOGIN, EMAIL = #EMAIL
WHERE ID = 1 AND LOGIN IS NULL
IF ##ROWCOUNT = 0
INSERT INTO Entities (LOGIN, EMAIL)
VALUES #LOGIN, #EMAIL
Unfortunately, it is not possible to include a WHERE condition into UPDATE statements in entity framework so you will have to select, then update or insert, e.g.:
using (var db = new EntityContext())
{
var ent = db.Entities.Where(x => x.ID == 1 && x.LOGIN == null).FirstOrDefault();
if (ent != null)
{
ent.LOGIN = "Whatever";
ent.EMAIL = "Whatever";
}
else
{
db.Entities.Add(ent);
}
db.SaveChanges();
}
I am new to entity framework and LINQ. I am stuck at an issue where I need to firstly check if the record already exists, if it exists then I need to update the record with column RESUMEID accordingly. If not then I need to add the record. I am able to add successfully but I don't know how to update the record in LINQ.
Below is my attempt:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ReferralViewModel viewModel)
{
var candidateId = User.Identity.GetUserId();
// I AM CONFUSED ABOUT BELOW STATEMENT
var IsDupeReferral = _context.Referrals
.Where(r => (r.CandidateId == candidateId)
&& (r.CompanyId == viewModel.CompanyId) && (r.SkillId == viewModel.SkillId))
.Select(r=>r.ReferralId).SingleOrDefault();
if(IsDupeReferral!=0)
{
//IF I FIND DUPE REFERRAL RECORD I WANT TO UPDATE SOME OF THE VALUES IN THAT
_context.Referrals.Where(r => r.ReferralId == IsDupeReferral).
AND UPDATE r.resumeId with viewModel.ResumeId // How to do this?
// NOT SURE ABOUT BELOW LINE EITHER
_context.SaveChanges();
}
else
{
// BELOW CODE IS WORKING FINE
var referral = new Referral
{
ReferralName = viewModel.ReferralName,
ResumeId = viewModel.ResumeId,
CandidateId = candidateId,
DegreeId = viewModel.DegreeId,
CoverLetterId = viewModel.CoverLetterId,
SkillId = viewModel.SkillId
};
if (!string.IsNullOrEmpty(viewModel.TempCompany))
{
var newCompany = new Company
{
CompanyName = viewModel.TempCompany
};
newCompany.Referrals.Add(referral);
_context.Companies.Add(newCompany); ;
}
else
{
referral.CompanyId = viewModel.CompanyId.Value;
_context.Referrals.Add(referral);
}
_context.SaveChanges();
}
return RedirectToAction("ReferralCenter");
}
Here's the solution
//IF I FIND DUPE REFERRAL RECORD I WANT TO UPDATE SOME OF THE VALUES IN THAT
var referral = _context.Referrals.FirstOrDefault(r => r.ReferralId == IsDupeReferral);
// AND UPDATE r.resumeId with viewModel.ResumeId
if (referral !=null) {
referral.resumeId = viewModel.ResumeId;
_context.Entry(referral).State = System.Data.EntityState.Modified;
_context.SaveChanges();
}
Actually, you don't need getting the IsDupeReferral and then request the record again. Try to combine your code as the following:
var referral = _context.Referrals
.Where(r => (r.CandidateId == candidateId)
&& (r.CompanyId == viewModel.CompanyId) && (r.SkillId == viewModel.SkillId)).SingleOrDefault();
if (referral !=null) {
referral.resumeId = viewModel.ResumeId;
_context.Entry(referral).State = System.Data.EntityState.Modified;
_context.SaveChanges();
}
else {
// add a new record
}
Referral referral = _context.Referrals.FirstOrDefault(r=> r.ReferralId = SomeId);
if(referral == null) // then referral does not exist - add it
{
referral = new Referral{
ReferralName = viewModel.ReferralName,
ResumeId = viewModel.ResumeId,
CandidateId = candidateId,
DegreeId = viewModel.DegreeId,
CoverLetterId = viewModel.CoverLetterId,
SkillId = viewModel.SkillId
};
_context.Referrals.Add(referral);
}
else // referral already exists - update its values
{
//make changes to referral
referral.ReferralName = viewModel.ReferralName;
referral.ResumeId = viewModel.ResumeId;
referral.CandidateId = candidateId;
referral.DegreeId = viewModel.DegreeId;
referral.CoverLetterId = viewModel.CoverLetterId;
referral.SkillId = viewModel.SkillId;
}
_context.SaveChanges(); //no matter added or updated - save the changes
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.
I have the following two lines of code which first returns an item from a query and then creates another item with the values of the first query. i would like to combine these two lines into one statement. Keep in mind that the result of the first query might be null on some occasions.
var x = uow.Profiles.FindByID(profileId).Competitor;
return Json(new Organisation() { Name = x.Name, ID = x.ID, IsClient = x.IsClient, IsDeleted = x.IsDeleted }, JsonRequestBehavior.AllowGet);
Maybe you can add a null check if this is your concern:
var result = uow.Profiles.FindByID(profileId);
if(result != null)
{
var competitor = result.Competitor;
return Json(new Organisation() { Name = competitor.Name, ID = competitor.ID, IsClient = competitor.IsClient, IsDeleted = competitor.IsDeleted }, JsonRequestBehavior.AllowGet);
}
return null; // or whatever you can default to
Not sure exactly what the problem is and how LINQ could help (you don't necessary have to use it), just make sure your code is readable.
Edit: finally using IEnumerable (I assume Profiles is one)
ouw.Profiles.Single(p => p.Id == profileId).Select
(p => Json(
new Organisation()
{
Name = p.Competitor.Name,
ID = p.Competitor.ID,
IsClient = p.Competitor.IsClient,
IsDeleted = p.Competitor.IsDeleted
},
JsonRequestBehavior.AllowGet)
);
I am inserting child records that are associated with an existing parent record. How would I refresh the parent record to show all, including the newly inserted, child records?
context.Refresh(RefreshMode.OverwriteCurrentValues, entity) isn't working.
A more complete example of my attempt:
Location newLocation = Json.deserialize<Location>(json);
if (newLocation != null) {
IEnumerable<string> zipCodes = Regex.Split(newLocation.zipCodes, #"[\s,;]+");
// this verifies the new zipcodes against a table of all US zipcodes and returns matches
var newLocationZipCodes = _zipCodeRepository.match(zipCodes).Select(item => new LocationZipCode { idLocation = newLocation.id, state = item.state, zipcode = item.zipcode });
// get the parent entity
var domainLocation = _unitOfWork.locationRepository.getFirst(l => l.id == newLocation.id);
// insert child entities
if (newLocationZipCodes.Any()) {
_unitOfWork.locationZipCodeRepository.insertAll(newLocationZipCodes);
_unitOfWork.saveChanges(ConflictMode.ContinueOnConflict);
}
// this isn't working
_unitOfWork.refresh(RefreshMode.OverwriteCurrentValues, domainLocation);
return domainLocation;
}
Here is a basic representation of the LocationZipCode class created by linq-to-sql:
public class LocationZipCode {
int idLocation;
string zipcode;
string state
EntityRef<Location> location;
}
And here is my refresh method in my UnitOfWork:
public void refresh(RefreshMode refreshMode, object entity) {
_context.Refresh(refreshMode, entity);
}
Instead of refreshing the context I changed the way I was inserting my child records into the database. So instead of...
_unitOfWork.locationZipCodeRepository.insertAll(newLocationZipCodes);
I'm doing this...
domainLocation.LocationZipCodes.AddRange(newLocationZipCodes);
So the updated code looks like so...
Location newLocation = Json.deserialize<Location>(json);
if (newLocation != null) {
IEnumerable<string> zipCodes = Regex.Split(newLocation.zipCodes, #"[\s,;]+");
var newLocationZipCodes = _zipCodeRepository.match(zipCodes).Select(item => new LocationZipCode { idLocation = newLocation.id, state = item.state, zipcode = item.zipcode });
var domainLocation = _unitOfWork..locationRepository.getFirst(l => l.id == newLocation.id);
if (newLocationZipCodes.Any()) {
domainLocation.LocationZipCodes.AddRange(newLocationZipCodes);
_unitOfWork.saveChanges(ConflictMode.ContinueOnConflict);
}
return new Mapper<DomainLocation, Location>(new LocationMapTemplate()).map(domainLocation);
}