C# MVC context.SaveChanges() do not persist data in database - c#

I´ve tried everything, read several questions here, but my code is still not working, and I can´t figure out what I´m doing wrong. The field 'liberado' in database doesn´t change to '1' after the code runned, and I get no errors. Thanks a lot.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Release(int id)
{
Publicacao publicacao = db.Publicacao.Find(id);
//Publicacao publicacao = db.Publicacao.Where(a => a.idpublicacao == id).First();
if (publicacao == null)
{
return RedirectToAction("Index");
}
db.Publicacao.Attach(publicacao);
db.Entry(publicacao).State = EntityState.Modified;
publicacao.liberado = 1;
db.SaveChanges();
return RedirectToAction("Index");
}
The model
public partial class Publicacao
{
public int idpublicacao { get; set; }
public string titulo { get; set; }
public string texto { get; set; }
public string imagem { get; set; }
public System.DateTime data { get; set; }
public int categoria { get; set; }
public byte[] arqimagem { get; set; }
public string descimagem { get; set; }
public Nullable<int> usuario { get; set; }
public int liberado { get; set; }
public virtual categoria categoria1 { get; set; }
public virtual Users Users { get; set; }
}

Related

Entity Framework: Can't save data because of tracking

I have got a complex class. Feedback and Steps. I am using SQL database and .NET Core 2. I can save main properties but can't save the sub class FeedbackSteps properties
public class FeedbackModel
{
[Key]
public int FeedBackID { get; set; }
public DateTime FBDate { get; set; }
public bool? VideoStatus { get; set; }
public string VideoDetail { get; set; }
public string PITFeedBack { get; set; }
public int ActivityID { get; set; }
public virtual ActivityModel Activity { get; set; }
public int ClientID { get; set; }
public virtual ClientModel Client { get; set; }
public int? SupportPlanID { get; set; }
public virtual SupportPlanModel SupportPlan { get; set; }
public int EmployeeID { get; set; }
public virtual Employee Employee { get; set; }
public bool FeedbackStatus { get; set; } = true;
virtual public List<FeedbackStepModel> FeedbackSteps { get; set; }
}
public class FeedbackStepModel
{
[Key]
public int FeedbackStepID { get; set; }
public int FeedbackID { get; set; } = 0;
public int SupportPlanID { get; set; }
public int StepNumber { get; set; }
public string StepDetail { get; set; }
public string AchievementStatus { get; set; }
public string AchievementComment { get; set; }
}
This is the post method. View returns Edited or Updated feedback and i just want to update the database with new data
[HttpPost]
public IActionResult Edit(FeedbackModel feedback)
{
if (ModelState.IsValid)
{
feedbackRepository.Save(feedback);
TempData["message"] = $"Feedback has been saved";
return RedirectToAction("Index");
}
}
After EDIT, I would like to save it...
public void Save(FeedbackModel feedback)
{
if (feedback.FeedBackID == 0)
{
context.FeedbackModels.Add(feedback);
}
else
{
FeedbackModel dbEntry = context.FeedbackModels.Include(s => s.FeedbackSteps).FirstOrDefault(a => a.FeedBackID == feedback.FeedBackID);
if (dbEntry != null)
{
dbEntry.FeedBackID = feedback.FeedBackID;
dbEntry.FBDate = feedback.FBDate;
dbEntry.VideoStatus = feedback.VideoStatus;
dbEntry.VideoDetail = feedback.VideoDetail;
dbEntry.SupportPlanID = feedback.SupportPlanID;
dbEntry.ActivityID = feedback.ActivityID;
dbEntry.PITFeedBack = feedback.PITFeedBack;
dbEntry.ClientID = feedback.ClientID;
dbEntry.EmployeeID = feedback.EmployeeID;
dbEntry.FeedbackStatus = feedback.FeedbackStatus;
dbEntry.FeedbackSteps = feedback.FeedbackSteps;
}
}
context.SaveChanges();
}
But I get this error all the time
The instance of entity type 'FeedbackStepModel' cannot be tracked because another instance with the key value '{FeedbackStepID: 1}' is already being tracked.
When attaching existing entities, ensure that only one entity instance with a given key value is attached.
Your FeedbackModel update operation with children (FeedbackSteps) should be as follows:
FeedbackModel dbEntry = context.FeedbackModels.Include(s => s.FeedbackSteps).FirstOrDefault(a => a.FeedBackID == feedback.FeedBackID);
if (dbEntry != null)
{
dbEntry.FeedBackID = feedback.FeedBackID;
dbEntry.FBDate = feedback.FBDate;
dbEntry.VideoStatus = feedback.VideoStatus;
dbEntry.VideoDetail = feedback.VideoDetail;
dbEntry.SupportPlanID = feedback.SupportPlanID;
dbEntry.ActivityID = feedback.ActivityID;
dbEntry.PITFeedBack = feedback.PITFeedBack;
dbEntry.ClientID = feedback.ClientID;
dbEntry.EmployeeID = feedback.EmployeeID;
dbEntry.FeedbackStatus = feedback.FeedbackStatus;
dbEntry.FeedbackSteps.Clear(); // First you have to clear the existing feedBackSteps
foreach(FeedbackStep feedBackStep in feedback.FeedbackSteps)
{
dbEntry.FeedbackSteps.Add(feedBackStep); // You have to add new and updated feedBackStep here.
}
}
If dbEntry.FeedbackSteps.Clear(); does not work (may be in EF Core 2.0 or lower Clear() does not work) then replace dbEntry.FeedbackSteps.Clear(); with the following code:
foreach(FeedbackStep feedbackStepToBeRemoved in dbEntry.FeedbackSteps)
{
context.Remove(feedbackStepToBeRemoved);
}

Dotnet Core Web API returning empty list | Lazy loading do not work

I have an endpoint in my API which returns all the data of a selected item. The item is a root object called Survey and it has a list of pages.
public partial class Surveys
{
public Surveys()
{
Pages = new HashSet<Pages>();
}
public string Description { get; set; }
public string Name { get; set; }
public long Syear { get; set; }
public long Quarter { get; set; }
public ICollection<Pages> Pages { get; set; }
}
Model class for the Pages look like this.
public partial class Pages
{
public Pages()
{
Elements = new HashSet<Elements>();
}
public string Id { get; set; }
public long Number { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int? PageFlowId { get; set; }
public bool NamedPage { get; set; }
public bool? IsFirst { get; set; }
public bool? IsLast { get; set; }
public long? SurveyQuarter { get; set; }
public long? SurveySyear { get; set; }
public PagesFlows PageFlow { get; set; }
public Surveys Survey { get; set; }
public ICollection<Elements> Elements { get; set; }
}
But when I send the GET request is returning an empty list for Pages
[
{
"description": "Customer Satisfaction Survey",
"name": "Customer Survey",
"syear": 2019,
"quarter": 1,
"pages": []
}
]
The database contains data. primary key of the table is a composite key(Syear, Quarter). My API looks like this.
public async Task<IActionResult> GetSurveys([FromRoute]long syear, long quarter)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var surveys = await _context.Surveys.Include(s => s.Pages).SingleOrDefaultAsync(s => s.Syear == syear && s.Quarter == quarter);
if (surveys == null)
{
return NotFound();
}
return Ok(surveys);
}
I have been trying to figure this out for a week now. Any help will be highly appreciated, Thank you in advance.
I managed to get around the issue by doing the following.
Removed .Include(s => s.Pages) from here,
var surveys = await _context.Surveys.Include(s => s.Pages).SingleOrDefaultAsync(s => s.Syear == syear && s.Quarter == quarter);
I have added virtual keyword to all the referenced classes.
public partial class Pages
{
public Pages()
{
Elements = new HashSet<Elements>();
}
public string Id { get; set; }
public long Number { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int? PageFlowId { get; set; }
public bool NamedPage { get; set; }
public bool? IsFirst { get; set; }
public bool? IsLast { get; set; }
public long? SurveyQuarter { get; set; }
public long? SurveySyear { get; set; }
public virtual PagesFlows PageFlow { get; set; }
public virtual Surveys Survey { get; set; }
public virtual ICollection<Elements> Elements { get; set; }
}
Then I have installed Microsoft.EntityFrameworkCore.Proxies package fron NuGet as described here
And enabled Lazy Loading Proxies in Sturtup.cs in ConfigureServices method.
services.AddDbContext<MyDBContext>
(options => options.UseLazyLoadingProxies().UseSqlServer(connection));

How do I post a one-to-many relationship?

Pretty new to ASP.NET and programming. I have two models, two API controllers, two repositories. How do I post the data to the second model while attaching it to the first (I'm guessing by ID.) Do I possibly need a View Model? Also reading a little about unit of work. Maybe neither are necessary? Below is some code. Thanks!
Record.cs
namespace Train.Models {
public class Record {
public int Id { get; set; }
public int Quantity { get; set; }
public DateTime DateCreated { get; set; }
public bool IsActive { get; set; }
public string UserId { get; set; }
public virtual ICollection<Cars> Cars { get; set; }
}
}
Cars.cs
namespace Train.Models {
public class Cars {
public int Id { get; set; }
public string EmptyOrLoaded { get; set; }
public string CarType { get; set; }
//Hopper, flatbed, tank, gondola, etc.
public string ShippedBy { get; set; }
//UP(Union Pacific) or BNSF
public string RailcarNumber { get; set; }
//public virtual ApplicationUser ApplicationUser { get; set; }
public string UserId { get; set; }
public string RecordId { get; set; }
public virtual Record Record { get; set; }
}
}
Record Repository
public void SaveRecord(Record recordToSave) {
if (recordToSave.Id == 0) {
recordToSave.DateCreated = DateTime.Now;
_db.Record.Add(recordToSave);
_db.SaveChanges();
} else {
var original = this._db.Record.Find(recordToSave.Id);
original.Quantity = recordToSave.Quantity;
original.IsActive = true;
_db.SaveChanges();
}
}
EFRepository (Cars)
public void SaveCar(Cars carToSave) {
if (carToSave.Id == 0) {
_db.Cars.Add(carToSave);
_db.SaveChanges();
} else {
var original = this.Find(carToSave.Id);
original.EmptyOrLoaded = carToSave.EmptyOrLoaded;
original.CarType = carToSave.CarType;
original.ShippedBy = carToSave.ShippedBy;
original.RailcarNumber = carToSave.RailcarNumber;
_db.SaveChanges();
}
}

ViewModel save selected value from dropdownlist

I have a dropdownlist - difficult. This is a dropdonwlinst where the user can select a value(easy, hard) but the value is not saved to the database, if I select a value. The strange thing I also have Country list, and that value is saved to the database.And If I put the values by hand in the database - for difficult the values are shown in the view
ModelVIew:
public RouteViewModel()
{
Countries = new List<SelectListItem>();
DifficultGrades = new List<SelectListItem>();
}
public int Id { get; set; }
[Required(ErrorMessage = "You need to give it a name")]
public string Name { get; set; }
public int SelectedValue { get; set; }
public int SelectedId { get; set; }
public IEnumerable<SelectListItem> Countries { get; set; }
public IEnumerable<SelectListItem> DifficultGrades { get; set; }
}
public class Difficult
{
[Key]
public int DifficultId { get; set; }
public string DifficultName { get; set; }
public virtual ICollection<Route> Routes { get; set; }
}
public class Route
{
[Key]
public int routeID { get; set; }
public string Name { get; set; }
public int? UserProfileID { get; set; }
public int? CountryID { get; set; }
public int? DifficultGradeID { get; set; }
public virtual UserProfile userProfile { get; set; }
public virtual Country country { get; set; }
public virtual Difficult difficult { get; set; }
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(RouteViewModel routeViewModel )
{
try
{
if (ModelState.IsValid)
{
var route = new Route();
UpdateRoute(route, routeViewModel);
db.Routes.Add(route);
db.SaveChangesAsync();
return RedirectToAction("Index");
}
}
catch (RetryLimitExceededException /* dex */)
{
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
}
ViewBag.Id = new SelectList(db.countries, "Id", "country_name", routeViewModel.Id);
ViewBag.DifficultId = new SelectList(db.difficulties, "DifficultId", "DifficultName", routeViewModel.Id);
return View(new RouteViewModel());
}
and the update method:
public void UpdateRoute(Route route, RouteViewModel routeViewModel )
{
route.routeID = routeViewModel.Id;
route.Name = routeViewModel.Name;
route.CountryID = routeViewModel.Id;
route.DifficultGradeID = routeViewModel.Id;
// climb.country.country_name = ModelViewClimb.Name;
}
Thank you

Im trying to get the last record submitted in the db using the repository pattern and MVC

Im trying to get the last record submitted in the db using the repository pattern and MVC. I am attaching the interface and class.And the controller where you can put the code. Please let me know if you need more details. Thanks.
public interface IRequestRepository
{
tblRequest GetCaseId(int caseId);
}
public class RequestRepository: IRequestRepository
{
helpdeskEntities context = null;
public RequestRepository()
{
context = new helpdeskEntities();
}
public string GetCaseId(Ticket ticket)
{
string caseId = string.Empty;
tblRequest tr = context.tblRequests.Where(u => u.CaseID == ticket.CaseID && u.UEmailAddress == ticket.UEmailAddress).SingleOrDefault();
if (tr != null)
{
caseId = tr.CaseID;
}
return caseId;
}
}
public class Ticket
{
public int CaseID { get; set; }
public string Title { get; set; }
[Required]
public string UFirstName { get; set; }
[Required]
public string ULastName { get; set; }
//public string UDisplayName { get; set; }
[Required]
public string UDep_Location { get; set; }
[Required]
public string UEmailAddress { get; set; }
//public string UComputerName { get; set; }
//public string UIPAddress { get; set; }
[Required]
public string UPhoneNumber { get; set; }
[Required]
public string Priority { get; set; }
[Required]
public string ProbCat { get; set; }
//public string IniDateTime { get; set; }
//public string UpdateProbDetails { get; set; }
//public string UpdatedBy { get; set; }
public string InitiatedBy_tech { get; set; }
public string AssignedBy { get; set; }
public string TechAssigned { get; set; }
[Required]
[DataType(DataType.MultilineText)]
public string ProbDetails { get; set; }
}
Controller
public ActionResult CreateTicket(tblRequest td)
{
}
First, you need to upgrade your IRequestRepository and add that method:
(I am assuming you're using EntityFramework for that)
public IRequestRepository
{
Request Latest(Ticket ticket);
}
Next, you need to implement that method in your RequestRepository:
public class RequestRepository : IRequestRepository
{
/* other code here */
public Request Latest(Ticket ticket)
{
// I'm also assuming you're using an auto incremented CaseId
return this.context.tblRequests.OrderByDescending(p => p.CaseId).FirstOrDefault(p => p.UEmailAddress == ticket.UEmailAddress);
}
}
And another thing:
Your IRequestRepository.GetCaseId implementation returns a string while it should return a tblRequest (one would also expect it to return an int Id...)
Anyway, I hope this helps!

Categories