How to update existing rows using Entity Framework? - asp.net-mvc

I have the following one to many table as below. I am experiencing issue when it comes to editing the existing rows with the following code. Please understand that I am pretty new to the ET relationship, so any detailed explanation would be greatly appreciated. Why it is returning null values?
public void UpdateReportGroup(TReportHeaderModel model)
{
if (model.THeaderTitle == null)
{
throw new Exception("Report Group Title must be filled in");
}
if (model.THeaderTitle.Length <= 0)
{
throw new Exception("A Report Group Title must be filled in.");
}
using (var connection = new TReportEntitiesConnection())
{
var header = connection.THeaders.SingleOrDefault(f => f.ID == model.ID);
var reports = connection.TReport.Where(f => f.THeaderID == model.ID);
connection.TReport.RemoveRange(reports);
foreach (var urls in model.TReports)
{
connection.TReport.Add(new TReport()
{
TReportName = urls.name,
URL = urls.url,
});
}
connection.THeaders.Add(header);
connection.SaveChanges()
}
}
Everytime, I debug it,it is giving null values for the 'TReport' table.
My create new rows works perfectly with the following code. Meaning, I am returning the correct form with correct field names.
public void CreateReport(TReportHeaderModel model)
{
if (model.THeaderTitle == null)
{
throw new Exception("Report Group Title must be filled in");
}
if (model.THeaderTitle.Length <= 0)
{
throw new Exception("A Report Group Title must be filled in.");
}
using (var connection = new TReportEntitiesConnection())
{
var header = new THeader()
{
ClientID = model.ClientID,
THeaderTitle = model.THeaderTitle,
RowNumber = model.RowNumber
};
foreach (var urls in model.TReports)
{
header.TReports.Add(new TReport()
{
TReportName = urls.name,
URL = urls.url
});
}
connection.THeaders.Add(header);
connection.SaveChanges();
}
}
As you can see, I am following DI pattern, and therefore I am calling these two methods in my controller as below:
[HttpPost]
public ActionResultModel CreateReportAPI([FromBody] TReportHeaderModel model) //attempt 3
{
try {
if (ModelState.IsValid)
{
var isValid = _tReportingService.HeadernameExists(model.THeaderTitle);
if (!isValid)
{
Console.WriteLine("it does not exist");
var user = this.GetCurrentUserAccount();
model.ClientID = user.SelectedClient.ID;
_tReportingService.CreateReport(model);
}
else //Update method comes till here and it goes //straight to the error
{
Console.WriteLine("it exists");
var user = this.GetCurrentUserAccount();
model.ClientID = user.SelectedClient.ID;
_tReportingService.UpdateReportGroup(model);
}
}
return new ActionResultModel()
{
Success=true,
Message="Report Group Successfully Saved."
};
}

I guess it would be the last time I'd posting questions here as I understood that it takes you nowhere if you just ask so I'd rather research more and keep trying it until I got it so here I am answering my own question as I'd solved it.
As the model gets generated from WebApi which is completely detached from ET, I am loading the database first and compare which children have been added, deleted & updated. Here is an example of perfect one to many relationship's update/delete.
using (var connection = new TReportEntitiesConnection())
{
var header = connection.THeaders.Include("TReports").SingleOrDefault(f => f.ID == model.ID);
if (header != null)
{
header.THeaderTitle = model.THeaderTitle; //update parent
}
foreach (var existingChild in header.TReports.ToList())
{
if (!model.TReports.Any(c => c.ID == existingChild.ID))
connection.TReport.Remove(existingChild);
}
foreach (var url in model.TReports)
{
var existingChild = header.TReports
.Where(c => c.ID == url.ID)
.SingleOrDefault();
if (existingChild != null)
{ //update child
connection.Entry(existingChild).CurrentValues.SetValues(url);
}
else
{
var newChild = new TReport
{
TReportName = url.name,
URL = url.url,
};
header.TReports.Add(newChild);
}
}
connection.SaveChanges();
}

Related

How to Detect state change in database table and add a schedule function to run at a specific time?

Let’s say I have a website where users can create questionnaires(Surveys) that get stored in the database for their users to answers the questions. My idea was to send an email notification to their users when the questionnaire has been changed for example a new question being added to the questionnaire.
However, to avoid send email every two minutes in case the user keeps on editing the questionnaire, I have created a temporary table ("LoggedSurveyUpdate") which will keep a record on when the questionnaire has been edited. Now the challenge that I am facing is that I would like the email notification to be sent an hour after the last questionnaire has been edited.
I hope this made sense.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(SurveyVM vm)
{
if (ModelState.IsValid)
{
try
{
bool readyToPublish = false;
if (vm.Survey.Publish)
{
readyToPublish = surveyLogic.CheckIfReadyToPublish(vm.Survey);
if (readyToPublish)
{
// User currentUser = userLogic.GetBy(x => x.UserID == vm.User.UserID);
Survey survey = surveyLogic.GetBy(x => x.SurveyName == vm.Survey.SurveyName && x.CustomerID == vm.Survey.CustomerID && x.SurveyID != vm.Survey.SurveyID).SingleOrDefault();
if (survey == null)
{
surveyLogic.Update(vm.Survey);
surveyLogic.SuveyUpdate(vm.Survey);
}
}
catch (Exception e)
{
vm.CategoryOptions = CategoryOptionsHelper.BuildCategoryOptions(vm.Survey.CustomerID, false);
TempData["Failure"] = "Edit Failed. Please Review Your Selections and Try Again.";
return View(vm);
}
}
}
Where data gets inserted in temporary table
public void SuveyUpdate(Survey survey)
{
using (ManageLoggedSurveyUpdate updateLogic = new ManageLoggedSurveyUpdate(ref base.Uow))
using (ManageSurvey surveyLogic = new ManageSurvey(ref base.Uow))
using (ManageLoggedSurveyUpdate loggedSurveyUpdate = new ManageLoggedSurveyUpdate(ref base.Uow))
{
Survey surveys = surveyLogic.GetBy(x => x.SurveyID == survey.SurveyID && x.Publish == survey.Publish).SingleOrDefault();
if (surveys == null)
{
LoggedSurveyUpdate newupdte = new LoggedSurveyUpdate()
{
SurveyID = survey.SurveyID,
Active = true,
SurveyEdited = DateTime.Now,
UserID = (int)System.Web.HttpContext.Current.Session["UserID"],
};
loggedSurveyUpdate.Insert(newupdte);
}
else {
LoggedSurveyUpdate newupdte = new LoggedSurveyUpdate()
{
SurveyID = survey.SurveyID,
Active = true,
SurveyEdited = DateTime.Now,
UserID = (int)System.Web.HttpContext.Current.Session["UserID"],
};
loggedSurveyUpdate.Update(newupdte);
}
}
}

Date validation(MVC)

Here is my code for controller to make an appointment.I would like to show error message to user if he/she choose date before today.How can I do it?
public ActionResult Make(Models.AppModel User)
{
if (Session["UserEmail"] != null)
{
using (var db = new MaindbModelDataContext())
{
var patient = db.Patients.FirstOrDefault(u => u.Email == (String)Session["UserEmail"]);
var app = new Appointment();
if(app.Date>System.Date){
app.Date = User.Date;
}
else{ModelState.AddModelError("Date", "Date is invalid");}
app.Description = User.Description;
app.Status = "isPending";
app.PatientNo = patient.PatientNo;
app.AppNo = Guid.NewGuid().GetHashCode();
db.Appointments.InsertOnSubmit(app);
db.SubmitChanges();
return RedirectToAction("Make", "Appointment");
}
}
else
{
return RedirectToAction("Index", "User");
}
}
}
The correct way to use DateTime to get the current date is DateTime.Now.Date. So in your code for example:
if (app.Date > DateTime.Now.Date)
The way your code is currently using the DateTime type is not valid.

Passing variable from one class to a view of a different class

I'm having a bit of trouble passing the variable score, that is a variable in my Evaluation class, that is initialized here in my [httpPost]ifstatements(Evaluation model) method in my Quiz controller to a view belonging to a different controller of a different class. When the score is greater than zero, i.e i answer at least one question correct, I am brought to the results view and the score is shown to me. But im having trouble printing that score out in another view called Index that is part of my index method in my LEADERBOARD controller of the LEADERBOARD class
Quiz Controller
public ActionResult ifStatement()
{
var evalVM = new Evaluation();
//the below is hardcoded for DEMO. you may get the data from some
//other place and set the questions and answers
var q1 = new Question { ID = 1, QuestionText = "1. Which of the following shows the correct syntax for an if statement?" };
q1.Answers.Add(new Answer { ID = 12, AnswerText = "a. if expression" });
q1.Answers.Add(new Answer { ID = 13, AnswerText = "b. if { expression }" });
q1.Answers.Add(new Answer { ID = 14, AnswerText = "c. if ( expression ){}" });
q1.Answers.Add(new Answer { ID = 15, AnswerText = "d. expression if" });
evalVM.Questions.Add(q1);
return View(evalVM);
}
[HttpPost]
public ActionResult ifStatement(Evaluation model)
{
int score = 0;
if (ModelState.IsValid)
{
using (UsersContext db = new UsersContext())
{
foreach (var q in model.Questions)
{
var qId = q.ID;
List<string> listSelectedAnswer = new List<string>();
listSelectedAnswer.Add("14");
listSelectedAnswer.Add("19");
listSelectedAnswer.Add("22");
listSelectedAnswer.Add("25");
listSelectedAnswer.Add("28");
listSelectedAnswer.Add("33");
foreach (string answer in listSelectedAnswer)
{
foreach (var answer2 in model.Questions)
{
if (answer == answer2.SelectedAnswer)
{
score = score + 3;
}
}
}
model.Score = score;
ViewBag.score = model.Score;
if (score > 0)
{
return View("results");
}
else
{
//score = 0;
//return Content("Please check all answers have been submitted!");
return Content("Error, please ensure all questions have been answered. You may use the back button to continue the Quiz."); //PRG Pattern
}
}
}
}
model.setScore(score);
return View("ThankYou");
}
Leaderboard Controller
public class LeaderboardController : Controller
{
UsersContext db = new UsersContext();
//
// GET: /Leaderboard/
TutorialEntities t = new TutorialEntities();
Evaluation e = new Evaluation();
public ActionResult Index()
{
// Evaluation ev = new Evaluation();
// var tutorial = t.Evaluations.ToList();
//ViewBag.Scores = t.Evaluations.Select(a => a.Score).ToList();
//ViewBag.Scores = e.getScore();
//ViewBag.Score = e.getScore();
ViewBag.Users = db.UserProfiles.ToList();
ViewBag.Scores = t.Evaluations.ToList();
return View();
}
}
Index View
<h2>Leaderboard</h2>
#foreach (var item2 in ViewBag.Users)
{
<p>
Score: #ViewBag.Score
</p>
}
#foreach (var item in ViewBag.Users)
{
<p>
UserID: #item.UserId
<br />
UserName: #item.UserName
<br />
</p>
}
All that shows on the page when i go this view is the name of the people who are registered on my website and their id but score is blank! I cant seem to get my head around it i have tried numerous ways but it seems it cant see the score that is being initialised in the ifstatement method
Your controller sets viewbag.scores, however your view is trying to access viewbag.score?

Displaying Data from the database taking Order Id as input in mvc4

I am new to asp and I would like to ask you for some help. I built store with MvcMusicStore tutorial help.Now I want to search in the database by using OrderId.As soon as the orderid is and if we click on the submit button it should display the corresponding rows from the database. My method is as follows
public ActionResult SearchOrder(int? myid)
{
var s = from sp in db.Railways
select sp;
string oid = myid.ToString();
if (!string.IsNullOrEmpty(oid))
{
s = s.Where(st => st.OrderID == (Convert.ToInt16(oid)));
}
return View(s.ToList());
}
Also i tired with the code as
public ActionResult SearchOrder(int? myid)
{
if (id != null)
{
if (ViewBag.OrderID == id.Value)
{
s = s.Where(st => st.OrderID == id);
}
}
return View(s);
}
In the second method when i tried it is neither displaying the contents nor showing the error.
Pls do help me.
Try this:
public ActionResult SearchOrder(int? myid)
{
var s = from sp in db.Railways
select sp;
if (myid.HasValue)
{
s = s.Where(st => st.OrderID == myid.Value);
}
return View(s.ToArray());
}
First your example will not work because string oid = myid.ToString(); will not be null or empty string if myid is null; Second example will fail (ViewBag.OrderID == id.Value) condition and moreover will not compile.

two models in a view - not working for me

I have created an entity data model from my database. however in certain areas of the application i need to pass two models. thus i create a third model which has as properties the objects of each required model.
In the scenario, i want to use one model just to show some data to the user and the other is to be populated by the user using form elements. therefore, i create a constructor in my custom model to populate it. here's the code:
THE CUSTOM MODEL
public class ordersModel
{
public ordersModel(order or)
{
this.prods = new order_products();
this.new_order = new order();
this.new_order.customer_id = or.customer_id;
this.new_order.my_id = or.my_id;
this.new_order.my_order_id = or.my_order_id;
this.new_order.order_date = or.order_date;
this.new_order.order_status_id = or.order_status_id;
}
public order new_order { get; set; }
public order_products prods { get; set; }
}
IT IS USED IN THE CONTROLLER AS FOLLOWS:
public ActionResult Create()
{
order or = new order();
// Store logged-in user's company id in Session
//or.my_id = Session["my_id"].ToString();
//do something to allow user to select customer, maybe use ajax
or.customer_id = "123";
or.order_amount = 0;
or.my_id = "74973f59-1f6c-4f4c-b013-809fa607cad5";
// display date picker to select date
or.order_date = DateTime.Now.Date;
// fetch statuses from database and show in select list box
or.order_status_id = 1;
return View(or);
}
//
// POST: /Orders/Create
[HttpPost]
public ActionResult Create(order or)
{
using (invoicrEntities db = new invoicrEntities())
{
var temp = db.last_order_number.SingleOrDefault(p => p.my_id == or.my_id);
if (temp != null)
{
or.my_order_id = temp.my_order_id + 1;
if (ModelState.IsValid)
{
ordersModel ord = new ordersModel(or);
db.orders.AddObject(or);
temp.my_order_id = temp.my_order_id + 1;
//TempData["my_order_id"] = or.my_order_id;
db.SaveChanges();
return RedirectToAction("AddProducts", ord);
//return RedirectToAction("AddProducts", new { id = or.my_order_id });
}
return View(or);
}
return RedirectToAction("someErrorPageDueToCreateOrder");
}
}
public ActionResult AddProducts()
{
using (invoicrEntities db = new invoicrEntities())
{
//string my_id = TempData["my_id"].ToString();
//string my_order_id = TempData["my_order_id"].ToString();
string my_id = "74973f59-1f6c-4f4c-b013-809fa607cad5";
int my_order_id = 1;
//Int64 my_order_id = Convert.ToInt64(RouteData.Values["order_id"]);
// Display this list in the view
var prods = db.order_products.Where(p => p.my_id == my_id).Where(p => p.my_order_id == my_order_id).ToList();
var or = db.orders.Where(p => p.my_id == my_id).Where(p => p.my_order_id == my_order_id).ToList();
if (or.Count == 1)
{
//ViewData["name"] = "sameer";
ViewData["products_in_list"] = prods;
ViewData["order"] = or[0];
return View();
}
return RedirectToAction("someErrorPageDueToAddProducts");
}
}
[HttpPost]
public ActionResult AddProducts(order_products prod)
{
prod.my_id = "74973f59-1f6c-4f4c-b013-809fa607cad5";
// find a way to get the my_order_id
prod.my_order_id = 1;
return View();
}
THIS ALL WORKS OUT WELL, UNTIL IN THE "ADDPRODUCTS" VIEW:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<invoicr.Models.ordersModel>" %>
AddProducts
<h2>AddProducts</h2>
<%: Model.new_order.my_id %>
the above statement gives an error
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
what am i doing wrong here?
You seem to be passing the wrong model when redisplaying your Create view.
Try passing the ord instance which is of type ordersModel and which is what your view is strongly typed to:
public ActionResult Create(order or)
{
using (invoicrEntities db = new invoicrEntities())
{
var temp = db.last_order_number.SingleOrDefault(p => p.my_id == or.my_id);
if (temp != null)
{
or.my_order_id = temp.my_order_id + 1;
ordersModel ord = new ordersModel(or);
if (ModelState.IsValid)
{
db.orders.AddObject(or);
temp.my_order_id = temp.my_order_id + 1;
db.SaveChanges();
return RedirectToAction("AddProducts", ord);
}
return View(ord);
}
return RedirectToAction("someErrorPageDueToCreateOrder");
}
}
UPDATE:
Now that you have shown your AddProducts action you are not passing any model to the view although your view expects an ordersModel instance. So don't just return View();. You need to pass an instance of ordersModel:
if (or.Count == 1)
{
ViewData["products_in_list"] = prods;
ViewData["order"] = or[0];
ordersModel ord = new ordersModel(or[0]);
return View(ord);
}

Resources