I am trying to perform CURD operation in MVC web application in a webgrid but the problem is I have multiple tables but don't know how to perform EDIT operation by using multiple tables.
Invoice table
public Invoice()
{
this.LineItems = new HashSet<LineItem>();
}
public int Customer_ID { get; set; }
public string Customer_name { get; set; }
public string Customer_Address { get; set; }
public virtual ICollection<LineItem> LineItems { get; set; }
Product Table
public Produc()
{
this.LineItems = new HashSet<LineItem>();
}
public int Product_ID { get; set; }
public string Product_name { get; set; }
public int Unit_Price { get; set; }
public virtual ICollection<LineItem> LineItems { get; set; }
LineItems Table
public partial class LineItem
{
public int Customer_ID { get; set; }
public int LineItems_ID { get; set; }
public int Product_ID { get; set; }
public int Quantity { get; set; }
public int Total { get; set; }
public virtual Invoice Invoice { get; set; }
public virtual Produc Produc { get; set; }
}
ViewModel
public class ViewModel
{
public string Customer_name { get; set; }
public string Customer_Address { get; set; }
public int Quantity { get; set; }
public int Total { get; set; }
public string Product_name { get; set; }
public int Unit_Price { get; set; }
}
here is a class which will perform CURD operation for me
public class Class1
{
SalesOrderEntities entities = new SalesOrderEntities();
public bool SaveStudent(ViewModel viewModel)
{
try
{
var Invoice = new Invoice()
{
Customer_name = viewModel.Customer_name,
Customer_Address = viewModel.Customer_Address
};
var LineItem = new LineItem()
{
Quantity = viewModel.Quantity,
Total = viewModel.Total
};
var Produc = new Produc()
{
Product_name=viewModel.Product_name,
Unit_Price=viewModel.Unit_Price
};
return true;
}
catch
{
return false;
}
}
public bool UpdateStudent()
{
try
{
}
catch (Exception)
{
throw;
}
}
Now, here i have problem i don't know how to perform edit functionality.
Updating using Entity Framework can be fairly straight-forward as it supports change-tracking by default. Change tracking will let EF automatically manage any changes that occur to your entities once they are pulled, so that when you call SaveChanges(), these same changes will be made at the database-level.
Example Adding New Entities
Since you already have your data context, when you are creating your new entities, you'll just need to ensure that you add them to the context properly and save the changes after that is done :
// Add each of your new entities to their appropriate table in the context and then save
// your changes
entities.Invoices.Add(new Invoice(){
Customer_name = viewModel.Customer_name,
Customer_Address = viewModel.Customer_Address
});
entities.LineItems.Add(new LineItem(){
Quantity = viewModel.Quantity,
Total = viewModel.Total
});
entities.Producs.Add(new Produc(){
Product_name = viewModel.Product_name,
Unit_Price = viewModel.Unit_Price
});
// Now save your changes
entities.SaveChanges();
Example Updating Existing Entities
Updating will essentially work the same way, however you will want to have access to the identifier so that you can query the existing entity, make your changes and save them :
public ActionResult UpdateStudent(int studentId)
{
using(var entities = new SalesOrderEntities())
{
// Get your student
var student = entities.Students.FirstOrDefault(s => s.StudentID == studentId);
if(student == null)
{
// Student wasn't found
return HttpNotFound();
}
// Create a view with the existing student data
return View(student);
}
}
[HttpPost]
public bool UpdateStudent(UpdateStudentViewModel viewModel)
{
try
{
using(var entities = new SalesOrderEntities())
{
// Retrieve your existing student (or other entities)
var existingStudent = entities.Students.FirstOrDefault(s => s.StudentID == viewModel.StudentID);
// Now that you have your entity, update the appropriate properties
existingStudent.Property = viewModel.Property;
// Then finally save your changes
entities.SaveChanges();
}
}
catch(Exception ex)
{
// Something went wrong updating the user
}
}
Related
I have successfully inserted data into two tables which are working fine. Now I am just stuck as to how I can get the details from both tables and update them. After inserting, I want to query both tables using an id and get the records, and then use the Id to update.
This is what I am looking for.
get data from two tables
update tables(pass id)
It must be an API that communicates with my classes because I want to display the data from the view
DB Models
1.
public class WholesaleRateSheetMarkup
{
[Key]
public int RateSheetMarkupId { get; set; }
[Required]
public int ResellerId { get; set; }
[StringLength(50)]
public string RatesheetName { get; set; }
}
2.
public class WholesaleRateSheet
{
[Key]
public int RateSheetId { get; set; }
[Required]
public int RateSheetMarkupId { get; set; }
public string CountryCode { get; set; }
public string Description { get; set; }
public decimal Peak { get; set; }
public bool IsSouthAfricanRate { get; set; }
public bool IsInertnationRate { get; set; }
public bool IsSpecificRate { get; set; }
public int DestinationGroupSetId { get; set; }
public int DestinationGroupId { get; set; }
public string DestinationLookup { get; set; }
public DateTime CreatedDate { get; set; }
public string CreatedByUsername { get; set; }
public DateTime LastUpdatedDate { get; set; }
public string UpdatedByUsername { get; set; }
}
My controller: This controller calls service class
[HttpPost]
[Route("[controller]/addRateSheet/{resellerId}/{productName}")]
public IActionResult AddRateSheet(int resellerId, string productName , int destinationGroupSetId, [FromBody]List<RateSheetSummary> rateSheetSummaries)
{
RateSheetService rateSheetService = new RateSheetService();
return Ok(rateSheetService.SaveRateSheet(resellerId, productName, rateSheetSummaries));
}
This is how I am saving to the database
public RateSheetModel SaveRateSheet(int resellerId, string productName, [FromBody]List<RateSheetSummary> rateSheetSummaries)
{
int latestId;
RateSheetModel rateSheetModel = new RateSheetModel();
try
{
#region Save rate sheet to the tabase
if (RateSheetObj != null)
{
#region WholesaleRateSheetMarkup
var wholesaleRateSheetMarkup = new WholesaleRateSheetMarkup
{
ResellerId = resellerId,
RatesheetName = productName,
};
_Context.WholesaleRateSheetMarkup.Add(wholesaleRateSheetMarkup);
_Context.SaveChanges();
//get latest RateSheetMarkupId
latestId = wholesaleRateSheetMarkup.RateSheetMarkupId;
#endregion
#region WholesaleRateSheet
#region commented out
List<WholesaleRateSheet> wholesaleRateSheets = new List<WholesaleRateSheet>();
foreach (var item in rateSheetSummaries)
{
wholesaleRateSheets.Add(new WholesaleRateSheet()
{
RateSheetMarkupId = latestId,
CountryCode = item.CountryCode,
Description = item.Description,
Peak = item.Peak,
IsSouthAfricanRate = item.IsSouthAfricanRate,
IsSpecificRate = item.IsSpecificRate,
DestinationGroupSetId = 1,
DestinationGroupId = 1,
DestinationLookup = item.DestinationLookup,
CreatedDate = DateTime.Now
}); ;
_Context.WholesaleRateSheet.AddRange(wholesaleRateSheets);
_Context.SaveChanges();
}
#endregion
}
}
}
}
Trying to fetch data from my tables. At this point, I don't know how to continue further as I want to get the details and so that I can bind the data from the view.
public RateSheetModel getRatesheetDetails(int rateSheetMarkupId)
{
RateSheetModel model = new RateSheetModel();
using (var context = new AppClientZoneContext())
{
var select = (from rsm in context.WholesaleRateSheetMarkup
join rs in context.WholesaleRateSheet
on rsm.RateSheetMarkupId equals rs.RateSheetMarkupId
where rsm.RateSheetMarkupId == rateSheetMarkupId
select new
{
rsm.RatesheetName,
rs.CountryCode,
rs.Description,
rs.Peak,
rs.IsSouthAfricanRate,
rs.IsInertnationRate,
rs.RateSheetMarkupId,
rs.IsSpecificRate,
rs.DestinationGroupSetId,
rs.DestinationGroupId,
rs.DestinationLookup,
rs.CreatedDate,
rs.CreatedByUsername,
rs.LastUpdatedDate,
rs.UpdatedByUsername,
}).FirstOrDefault();
}
return model;
}
Update API
[HttpPost]
[Route("[controller]/updateRateSheet/{resellerId}/{ratesheetId}")]
public IActionResult UpdateRateSheet(int resellerId, int ratesheetId, string productName)
{
RateSheetService UpdateRateSheetService = new RateSheetService();
return Ok(UpdateRateSheetService.UpdateRateSheet(resellerId,ratesheetId, productName));
}
Update function: I don't know how to best approach update functionality
public RateSheetModel UpdateRateSheet(int resellerId, int rateSheetId, string productName)
{
RateSheetModel mm = new RateSheetModel();
return mm;
}
I am going to create an app in Xamarin forms and starting with SQLite. I need to have unique list items for each Main item in the app.
For example, I am having a list with items. When I am selecting an item in the list a new page will pop up and display the items of that item.
So from my point of view I am in need of two SQLite tables with relations between.
This is the Main table with all profiles
[Table("Profiles")]
public class ProfileItems
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string ProfileName { get; set; }
public string ProfileRace { get; set; }
public string iconn = "icon.png";
public string ProfileIcon { get; set; }
public DateTime BDay { get; set; }
[OneToMany(CascadeOperations = CascadeOperation.All)]
public List<LoggItems> Loggs { get; set; }
}
This is the logg table for each Profile, which should be unique for each profile
[Table("Loggs")]
public class LoggItems
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string Title { get; set; }
public string Text { get; set; }
[ForeignKey(typeof(ProfileItems))]
public int ProfileId { get; set; }
}
Adding the items like this
public class ProfileDatabase
{
readonly SQLiteAsyncConnection database;
public ProfileDatabase(string dbPath)
{
database = new SQLiteAsyncConnection(dbPath);
database.CreateTableAsync<ProfileItems>().Wait();
database.CreateTableAsync<LoggItems>().Wait();
}
//Profile
public Task<List<ProfileItems>> GetProfileAsync()
{
return database.Table<ProfileItems>().ToListAsync();
}
public Task<ProfileItems> GetProfileAsync(int id)
{
return database.Table<ProfileItems>().Where(i => i.Id == id).FirstOrDefaultAsync();
}
public Task<int> SaveProfileAsync(ProfileItems profileItems)
{
if (profileItems.Id != 0)
{
return database.UpdateAsync(profileItems);
}
else
{
return database.InsertAsync(profileItems);
}
}
public Task<int> DeleteProfileAsync(ProfileItems profileItems)
{
return database.DeleteAsync(profileItems);
}
//Logg
public Task<List<LoggItems>> GetLoggAsync()
{
return database.Table<LoggItems>().ToListAsync();
}
public Task<LoggItems> GetLoggAsync(int id)
{
return database.Table<LoggItems>().Where(i => i.Id == id).FirstOrDefaultAsync();
}
public Task<int> SaveLoggAsync(LoggItems loggItems)
{
if (loggItems.Id != 0)
{
return database.UpdateAsync(loggItems);
}
else
{
return database.InsertAsync(loggItems);
}
}
public Task<int> DeleteLoggAsync(LoggItems loggItems)
{
return database.DeleteAsync(loggItems);
}
}
Both Logg and Profile list/tables do work but they do not have any relations between so the loggs show the same in all profile.
How should I do this?
How about to use Linq and join the relationships.
1.- First you have to add the namespace:
using System.Linq;
2.- Change the property in the class ProfileItems to be a IEnumerable
[OneToMany(CascadeOperations = CascadeOperation.All)]
public virtual IEnumerable<LoggItems> Loggs { get; set; }
3.- This is the method to join the loggs with the profile items.
var profiles = await GetProfileAsync();
var loggs = await GetLoggAsync();
var query = from p in profiles
join l in loggs on p.Id equals l.ProfileId into list
select new ProfileItems
{
Id = p.Id,
ProfileIcon = p.ProfileIcon,
ProfileName = p.ProfileName,
ProfileRace = p.ProfileRace,
BDay = p.BDay,
Loggs = list
};
I think you must add "virtual" keyword for enabling lazy loading.
[OneToMany(CascadeOperations = CascadeOperation.All)]
public virtual List<LoggItems> Loggs { get; set; }
And there's the "[InverseProperty]" to specify their related navigation property.
public class LoggItems
{
*
[ForeignKey(typeof(ProfileItems))]
[InverseProperty("Loggs")]
public int ProfileId { get; set; }
*
}
Title says it all, right now I have a single table that is populated from a linq query and I want to add more tables with different linq queries. I'm kinda lost on how would I do that..
I could probably do it if I create different views for each table but I want to have just one view for all. :D
Here's my code: (It's a table for "on going" projects)
Controller:
public ActionResult Index()
{
var project = from x in db.Projects
where x.Project_Status == "Ongoing"
select x;
return View(project);
}
Model:
public class Project
{
[Key]
public int Project_Id { get; set; }
public string Project_Name { get; set; }
public string Project_Detail { get; set; }
public string Project_Status { get; set; }
public int Employee_Id { get; set; }
}
View Model:
public class AdminHomeViewModel
{
public Project Ongoing { get; set; } //table for ongoing projects
public Project NYA { get; set; } //another table for Not Yet Assigned projects
public Employee Free { get; set; } //another table for free employees
public List<Project> OngoingList { get; set; }
public List<Employee> NYAList { get; set; }
public List<Employee> FreeList { get; set; }
}
You are confusing yourself with the different types of models. You should have a clear understanding between View-Model and Data-Model. You should always return View-Model to the View, and not the Data-Model. Data-Model are just the POCO classes which represents your data framework (in this case, each tables). There should be different Data Models for each of your table, which you must be having already based on your entity-framework approach (Code first, Model first or Database first). Then, prepare a single model for your view (as we can bind only one model to one view). Keep all the fields from different Data-Models that you need in that View and pass it along. See the approach below:
Data-Models
public class Project
{
[Key]
public int Project_Id { get; set; }
public string Project_Name { get; set; }
public string Project_Detail { get; set; }
public string Project_Status { get; set; }
public int Employee_Id { get; set; }
}
public class Employee
{
[Key]
public int Employee_Id { get; set; }
public string Employee_Name { get; set; }
public string Employee_Detail { get; set; }
}
View-Model
public class MyViewModel
{
public int Project_Id { get; set; }
public string Project_Name { get; set; }
public string Project_Detail { get; set; }
public string Project_Status { get; set; }
public int Employee_Id { get; set; }
public string Employee_Name { get; set; }
public string Employee_Detail { get; set; }
}
Or
public class MyViewModel
{
public Project proj { get; set; }
public Employee emp { get; set; }
}
Pass it to view as:
public ActionResult Index()
{
MyViewModel model = new MyViewModel();
// You linq query to populate model goes here
return View(model);
}
Update:
From my understanding, you need something like this:
View-Model:
public class AdminHomeViewModel
{
public AdminHomeViewModel()
{
Ongoing = new List<Project>();
NYA = new List<Project>();
Free = new List<Employee>();
}
public List<Project> Ongoing { get; set; } //table for ongoing projects
public List<Project> NYA { get; set; } //another table for Not Yet Assigned projects
public List<Employee> Free { get; set; } //another table for free employees
}
Controller:
public ActionResult Index()
{
AdminHomeViewModel model = new AdminHomeViewModel();
var result1 = (from x in db.Projects
where x.Project_Status == "Ongoing"
select new Project(){
Project_Id = x.Project_Id ,
Project_Name = x.Project_Name,
... //all other assignments goes here
}).ToList();
var result2 = (from x in db.Projects
where x.Project_Status == "blah blah"
select new Project(){
Project_Id = x.Project_Id ,
Project_Name = x.Project_Name,
... //all other assignments goes here
}).ToList();
var result3 = (from x in db.Employee
where x.AnyCondition == "blah blah"
select new Employee(){
Employee_Id = x.Employee_Id ,
Employee_Name = x.Employee_Name,
... //all other assignments goes here
}).ToList();
model.Ongoing = result1;
model.NYA = result2;
model.Free = result3;
return View(model);
}
I have two API calls. GetExam and SaveExam. GetExam serializes to JSON which means by the time I go to save, the entity is detached. This isnt a problem, I can go retrieve the entity by its primary key and update its properties manually.
However, when I do so the exam questions get its current collection duplicated. For example, if examToSave.ExamQuestions had a few questions deleted, and a new one added all selectedExam.exam_question are duplicated and the new one is added in. Eg. if 3 questions existed, I deleted 1 and added 4 there will now be 7.
Domain models:
public partial class exam
{
public exam()
{
this.exam_question = new HashSet<exam_question>();
}
public int ID { get; set; }
public string ExamName { get; set; }
public string ExamDesc { get; set; }
public Nullable<decimal> TimeToComplete { get; set; }
public bool AllowBackStep { get; set; }
public bool RandomizeAnswerOrder { get; set; }
public int Attempts { get; set; }
public virtual ICollection<exam_question> exam_question { get; set; }
}
public partial class exam_question
{
public exam_question()
{
this.exam_answer = new HashSet<exam_answer>();
}
public int ID { get; set; }
public int ExamID { get; set; }
public string QuestionText { get; set; }
public bool IsFreeForm { get; set; }
public virtual exam exam { get; set; }
public virtual ICollection<exam_answer> exam_answer { get; set; }
}
public partial class exam_answer
{
public int ID { get; set; }
public string AnswerText { get; set; }
public int QuestionID { get; set; }
public bool IsCorrect { get; set; }
public virtual exam_question exam_question { get; set; }
}
Save method:
[Route("SaveExam")]
[HttpPost]
public IHttpActionResult SaveExam(ExamViewModel examToSave)
{
using (var db = new IntranetEntities())
{
// try to locate the desired exam to update
var selectedExam = db.exams.Where(w => w.ID == examToSave.ID).SingleOrDefault();
if (selectedExam == null)
{
return NotFound();
}
// Redacted business logic
// Map the viewmodel to the domain model
Mapper.CreateMap<ExamAnswerViewModel, exam_answer>();
Mapper.CreateMap<ExamQuestionViewModel, exam_question>().ForMember(dest => dest.exam_answer, opt => opt.MapFrom(src => src.QuestionAnswers));
Mapper.CreateMap<ExamViewModel, exam>().ForMember(dest => dest.exam_question, opt => opt.MapFrom(src => src.ExamQuestions));
var viewmodel = Mapper.Map<exam>(examToSave);
// Update exam properties
selectedExam.ExamName = viewmodel.ExamName;
selectedExam.ExamDesc = viewmodel.ExamDesc;
selectedExam.AllowBackStep = viewmodel.AllowBackStep;
selectedExam.Attempts = viewmodel.Attempts;
selectedExam.RandomizeAnswerOrder = viewmodel.RandomizeAnswerOrder;
selectedExam.exam_question = viewmodel.exam_question; // DUPLICATES PROPS
// Save
db.SaveChanges();
return Ok(examToSave);
}
}
I have the following classes:
public class Order
{
public Order() { LineItems = new List<OrderLineItem>(); }
public int OrderID { get; set; }
..
public virtual ICollection<OrderLineItem> LineItems { get; set; }
..
}
public class OrderLineItem
{
public int OrderLineItemID { get; set; }
public int ProductID { get; set; }
public virtual Product Product { get; set; }
public int Quantity { get; set; }
}
public class Product
{
public int ProductID { get; set; }
...
}
When I persist Order, I have set the OrderLineItems to the appropriate field. However, after I have saved it to the database with the following code:
public void SaveOrder(Order ord)
{
if (ord.OrderID == 0)
{
context.Orders.Add(ord);
}
else
{
var currentCat = context.Orders.Find(ord.OrderID);
if (currentCat != null)
context.Entry(currentCat).CurrentValues.SetValues(ord);
else
context.Entry(ord).State = EntityState.Modified;
}
context.SaveChanges();
}
The OrderLineItem.Product object is null. It has the appropriate ProductID set, but it doesn't populate the actual product. I have tried a few different mappings similar to the following, but I'm a bit new to entity framework.
modelBuilder.Entity<OrderLineItem>()
.HasRequired(c => c.Product);
Any help would be most appreciated.
I believe you have to iterate through the products and Add() them as well.