Entity Framework ViewModel with Multiple Tables - asp.net-mvc

I am building MVC CRUD pages for the Events table, where I have one to many between table (C) DeviceChannel and table (D) Events. Table (C) is described by a 2 foreign keys to tables (A) Device and (B) Channel. There is a further foreign key to describe the EventType.
The DeviceChannel does not have a description (so I can't use this as the look up for Events directly) though it does have various values associated with it so I have to include the Device and Channel tables.
I have built a ViewModel with the above tables but when I try to create a Controller, I get errors complaining there is no Metadata for the ViewModel. No keys defined between the tables. All the tables have keys and load up correctly in EF database-first.
I am using VS2013 with .Net 4.5.2
I did try using a repository after following the NerdDinners example, without success.
Questions:
Should I be using a ViewModel to develop this solution.
If I use a ViewModel, how do I resolve the metadata/key issue when trying to scafold the controller?

I solved this issue by simplifying the ViewModel.
public class DeviceChannelEventsViewModel
{
public SelectList eventType { get; private set; }
public SelectList deviceChannel { get; private set; }
public CRHSEvent crhsEvent { get; set; }
public DeviceChannelEventsViewModel(SelectList _deviceChannel, SelectList _eventType, CRHSEvent _crhsEvent)
{
deviceChannel = _deviceChannel;
eventType = _eventType;
crhsEvent = _crhsEvent;
}
public DeviceChannelEventsViewModel(SelectList _deviceChannel, SelectList _eventType)
{
deviceChannel = _deviceChannel;
eventType = _eventType;
crhsEvent = new CRHSEvent();
}
}
When I created the selectlist for deviceChannel, I joined the Device and Channel tables to the devicechannel table:
DeviceChannelRepository dcr = new DeviceChannelRepository();
IEnumerable<DeviceChannel> dc = dcr.FindAllDeviceChannelsDescribed();
SelectList deviceChannels = new SelectList(dc.Select(s => new
{
DeviceChannelID = s.DeviceChannelID ,
DCDescription=string.Format("{0} | {1}",s.Device.DeviceName,s.Channel.Description)
}).ToList(), "DeviceChannelID", "DCDescription");
SelectList eventType = new SelectList(db.EventType, "EventTypeID", "Description");
DeviceChannelEventsViewModel dCEViewModel =
new DeviceChannelEventsViewModel(deviceChannels, eventType);

Related

EF 6.0 - Map complex type to same table as parent property

I have looked at the following:
Entity framework code first map multiple complex types of the same type to a table
Given the example code:
[Table("TXLifeRequest", Schema = "txlife")]
public partial class TXLifeRequest
{
public virtual OLI_LU_BOOLEAN PendingResponseOK { get; set; }
...
}
[Table("OLI_LU_BOOLEAN", Schema = "txlife")]
public partial class OLI_LU_BOOLEAN {
public string tc { get; set; }
public string Value { get; set; }
}
I would like to structure the database so that the OLI_LU_BOOLEAN is not in a new table, rather to be two new columns in the TXLifeRequest table as something like TXLifeRequest.PendingResponseOK_tc and PendingResponseOK _Value.
There is no fluent code in the existing context. Is there a way to do this either by fluent or attrubutes so that the class structure is intact but the tables are combined?
Update:
I have tried the following but it creates a new table TXLifeRequest1 for all of the OLI_LU_BOOLEAN properties. How would I specify these as properties of same table?
modelBuilder.ComplexType<OLI_LU_BOOLEAN>()
CreateTable("imsparamed.TXLifeRequest1",
c => new
{
Id = c.Int(nullable: false, identity: true),
PendingResponseOK_Value = c.String(),
PendingResponseOK_Id = c.Int(nullable: false)
})
The solution is to create a complex type:
modelBuilder.ComplexType<OLI_LU_BOOLEAN>().Ignore(i => i.Value);

Asp.net mvc call entity db data using Id for that particular row

Hi and thank you for taking your time to read. I am having trouble calling from a db using entity framework for a particular row. Here is my code for controller.
public ActionResult MyAccount(CurrentAccount ca, SaverAccount sa, int id)
{
var model = db.CurrentAccounts.FirstOrDefault(_ => _.Id == id);
Session["Id"] = ca.Id;
Session["CurrentAccountNumber"] = ca.CurrentAccountNumber;
Session["CurrentBalance"] = ca.CurrentBalance;
Session["SaverAccountNumber"] = sa.SaverAccountNumber;
Session["CurrentBalance"] = sa.SaverAccountNumber;
return View(model);
}
My model is a edmx entity file and i can seem to retrieve some data to my locals but only from 1 table and i need data to be from multiple tables selecting a full row of data for a paricular Id then having this information visable on the same view. There is also a relation between id on both tables. Thanks :)
Here you have called wrong object because you are fetching data in model variable but calling from ca. please use as following
public ActionResult MyAccount(CurrentAccount ca, SaverAccount sa, int id)
{
var model = db.CurrentAccounts.FirstOrDefault(_ => _.Id == id);
Session["Id"] = model.Id;
Session["CurrentAccountNumber"] = model.CurrentAccountNumber;
Session["CurrentBalance"] = model.CurrentBalance;
Session["SaverAccountNumber"] = sa.SaverAccountNumber;
Session["CurrentBalance"] = sa.SaverAccountNumber;
return View(model);
}
You need to execute join query to get data from two models like following exmaple
Create a common class like follwing
public class datafrombothclass
{
public int Id { get; set; }
public String saveaccount_name { get; set; }
public String currrentaccount_name { get; set; }
}
Now use join query in entity framework to get data from both model in you case from CurrentAccount and SaverAccount.
See the bellow code example:
var frombothclass=(from a in Model.saveaccount join s in Model.currentaccountaccount
where a.Id=id
select new datafrombothclass{
Id=a.Id,
saveaccount_name=s.name,
currrentaccount_name=a.name
});
return View(frombothclass);
Hope you will get the solution.

Simple approach to CRUD intersection table in MVC ASP.NET and EF?

I am using C#, MVC3, EF5, SQL Server 2008 R2.
I have an intersection table ie
Lecturer -< LecturerCourse >- Course
The list of Lecturers are populated.
When I add a course, it would be neat to have a list of Lecturers that I could select from, that teach the course in question. When I save the new Course record, this multiselect also should save its data back to the "LecturerCourse" table via Model Binding.
I am using EF5.
Can you recommended a simple and standard approach to solving CRUD for a join, ie "LecturerCourse", table? I have looked online, but some of the approaches seem very complicated.
Many thanks.
Alright, it's going to be a long one. To allow this to happen in "one page" (through POST, or you could use Ajax, technically), you need a combination of a Get and Post version of the method and to construct your view model correctly. Below are the classes that I will use for demonstration purposes:
public class NewCourse
{
[Required]
public string Name { get; set; }
// And your other properties
public int[] LecturerIds { get; set; }
}
public class ViewLecturer
{
public int Id { get; set; }
public int Name { get; set; }
}
public class NewCourseViewModel
{
public NewCourse Course { get; set; }
public IEnumerable<ViewLecturer> Lecturers { get; set; }
}
NewCourseViewModel will be the model for the View (see below). ViewLecturer will give you a lighter mapping between your available Lecturer and the information required to Add to them.
As for the Controller:
public class CourseController : Controller, IDisposable
{
private Lazy<YourContext> lazyContext =
new Lazy<YourContext>(() => new YourContext());
private YourContext Context
{
get { return lazyContext.Value; }
}
public ActionResult New()
{
var model = new NewCourseViewModel {
Course = new NewCourse(),
Lecturers = Context.Lecturers
.Select(l => new ViewLecturer { Id = l.Id, Name = l.Name })
};
return View(model);
}
[HttpPost]
public ActionResult New(NewCourse course)
{
if(ModelState.IsValid)
{
var lecturers = course.Lecturers
.Select(l => new Lecturer { Id = l.Id })
.ToList();
foreach(var lecturer in lecturers)
Context.Lecturers.Attach(lecturer);
var newCourse = new Course {
Name = course.Name,
// ... and the rest of the mapping
Lecturer = lecturers
};
context.Courses.Add(newCourse);
context.SaveChanges();
// Could have to handle DbUpdateException if you want
return RedirectToAction(...);
}
return View(new NewCourseViewModel {
Course = course,
Lecturers = Context.Lecturers
.Select(l => new ViewLecturer { Id = l.Id, Name = l.Name })
});
}
public void Dispose()
{
if(lazyContext.IsValueCreated)
lazyContext.Value.Dispose();
}
}
Your first New method will give you the entry point for your Course creation page. The rest of the validation and actual adding will be done through the [HttpPost]overload. As for your View (that should be in the ~/Views/Course/New.cshtml):
#model NewCourseViewModel
// ... Then when you are ready to begin the form
#using(Html.BeginForm("New", "Course", FormMethod.Post))
{
// Your List of Lecturers
#Html.ListBoxFor(m => m.Course.LecturerIds,
new MultiSelectList(
Model.Lecturers,
"Id",
"Name",
m.Course.LecturerIds ?? new int[0]
))
// Your Other Model binding
}
When the submit button will be pressed, the action matched will be the New(NewCourse course). The names are important because of the way the HtmlHelpers generate their Ids. Because we are only included one property of the whole view model, it will match the parameter name course based on the view model's Course property. You will get a list of Ids for the Lecturers which you will be able to use to attach to the DbContext and add directly to the new Course model (Entity Framework will do the rest). In cases where there was a problem, we can get back the list of lecturers and re-use the same NewCourse in the view model.
Now this is example is very basic but it should give you a good starting point as to how you can structure your view model.

ASP.NET MVC - updating foreign keys

I am just starting to investigate ASP.NET MVC, and I am using the latest beta (ie. 4). I'm after the correct approach to what is a fairly CRUD scenario. My main table (Task) looks something like this -
TaskID (int)
EmployeeID (int)
ProjectID (int)
DeptID (int)
Comment (varchar)
Date (datetime)
Hours (float)
TaskID is the primary key. The other three IDs are all foreign keys into reference tables.
Following various tutorials, I created an object model (.edmx) using Entity Framework. I then autogenerated the controller using "Add... Controller" and selecting the "Controller with read/write..." template.
All worked well. However, obviously I want the three foreign key columns to display lookup values from the reference tables, rather than the ID. I'm really not sure what the "best practice" method for achieving this is. A few options occur to me -
Create a view in SQL Server
Create a view in EF (not sure how this is done)
Look up the reference values on the fly using LINQ in the controllers
Perhaps there are other ways. I would like to hear from experienced MVC progs regarding "best practice" in this scenario.
would prefer to have TaskViewModel class which will have properties something like this
public class TaskViewModel
{
public Task Task { get; set; }
public Dictionary<int, string> ProjectList { get; set; }
//rest of the Lookup Properties like DeptList, EmpList
}
public class Task
{
public int TaskId { get; set; }
public int projectId { get; set; }
//Rest of the properties
}
And would use
#model TaskViewModel
#Html.DropDownListFor(m => m.Task.projectId, new SelectList(Model.ProjectList, "key", "value", Model.Task.projectId))%>

Stored Procedure Multiple-Table Output With LINQ and ASP.NET MVC

Quite often our systems call stored procedures which output multiple tables worth of results. Previously we used XML outputs to get each table and relate them correctly using XSLT. If I were using ASP.NET MVC with LINQ calling a stored procedure, how do I get each of the tables and then output the data as necessary?
this article here explains everything. This is the same article which i linked, in your previous SO question.
There's an article here about LINQ to SQL and stored procedures, especially the section 'Handling Multiple Result Shapes from SPROCs':
LINQ to SQL - Retrieving Data Using Stored Procedures.
Is that useful in your case?
Otherwise, not using LINQ to SQL, maybe use SqlDataReader's NextResult to go through the results, for example:
IList<Employee> employees = new List<Employee>();
IList<Customer> customers = new List<Customer>();
using (SqlConnection connection = new SqlConnection
(Properties.Settings.Default.NorthwindConnectionString))
using (SqlCommand command = new SqlCommand
("GetEmployeesAndCustomers", connection))
{
command.CommandType = CommandType.StoredProcedure;
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
Employee e = new Employee{EmployeeID = (int)reader["EmployeeID"]};
employees.Add(e);
}
reader.NextResult();
while (reader.Read())
{
Customer c = new Customer{CustomerID = (string)reader["CustomerID"]};
customers.Add(c);
}
}
}
Edit: Example of how to handle custom data combinations that are not easily fit into domain model objects; in this case retrieving orders along with the customers for the orders:
namespace Company.Application.ViewModel
{
public class CustomerOrder
{
public string CustomerID { get; set; }
public string CustomerName { get; set; }
public int OrderID { get; set; }
public DateTime? OrderDate { get; set; }
}
}
namespace Company.Application.Repository
{
public class CustomerOrderRepository
{
public IList<CustomerOrder> GetCustomerOrders()
{
NorthwindDataContext db = new NorthwindDataContext();
var custorders = from customer in db.Customers
join order in db.Orders
on customer.CustomerID equals order.CustomerID
select new CustomerOrder
{
CustomerID = customer.CustomerID,
CustomerName = customer.CompanyName,
OrderID = order.OrderID,
OrderDate = order.OrderDate
};
return custorders.ToList();
}
}
}
Inspiration for this: In the chapter about NerdDinner, Scott Guthrie talks about creating custom 'ViewModel' objects to hold data from for example joins that are not easily fit into the domain model objects.

Resources