Multiple tables with different LINQ queries in a single view - c#

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);
}

Related

grouping results in a view ASP.NET

I'm using ASP.NET Core 2.2. I have 2 models and a viewmodel which injects data to a view. I want to order results based on their productType. Let's make it clear
This is Product model
public class Product
{
public int ProductID { get; set; }
public int ProductName { get; set; }
public string ProductImage { get; set; }
public int ProductTypeID { get; set; }
[ForeignKey("ProductTypeID")]
public virtual ProductType ProductType{ get; set; }
}
This is ProductType model
public class ProductType
{
public int ProductTypeID { get; set; }
public int ProductTypeName { get; set; }
public string ProductTypeImage { get; set; }
public string ProductTypeDescription { get; set;
}
And finally this is DishesViewModel
public class DishesVM
{
public IEnumerable<ProductType> ProductType { get; set; }
public IEnumerable<Product> Product { get; set; }
}
In MyController I get data from DB then with automapper, map them to DishViewModel
public class HomeController : Controller
{
public IActionResult Dishes()
{
var productTypes= _context.ProductType.OrderBy(p =>p.ProductTypeID).ToList();
var products= _context.Products.OrderBy(p => p.ProductID).ToList();
var DishesVM = new DishesVM();
DishesVM.ProductType = _mapper.Map<IEnumerable<ProductType>>(productTypes);
DishesVM.Product = _mapper.Map<IEnumerable<Product>>(products);
}
}
Now in Dishes View I can have nested foreach
#model DishesViewModel
<div>
foreach(var pt in Model.ProductType)
{
<h1>pt.ProductTypeName</h1>
foreach(var p in Model.Product)
{
p.ProductName
}
}
</div>
This works fine but the only problem it has, is it returns all products. but I want each Product Category has its Products In front of its header. This is visual representation of what I want and what I have now.
This is what I want
But this is what I have
You have to filter your products by product type in each iteration. At the moment you just display all products for each product type:
<div>
foreach(var type in Model.ProductType)
{
//products which belong to the particular type
var productsForType = Model.Product.Where(x => x.ProductTypeID == type.ProductTypeID);
<h1>pt.ProductTypeName</h1>
foreach(var product in productsForType)
{
product.ProductName
}
}
</div>
This will give you a jump on the linq statement:
var list = productTypes.Where(x => x.ProductTypeID == 1).Select(x => new Product()
{
ProductImage = x.ProductTypeImage,
}).ToList();
You will need to decide on what to put into the where clause, I'm using ProductTypeID

How to get specific columns with one to many relationship

I have 3 tables , one to many relationship.
I need to get only specific columns with SelectMany method.
I need to get only Categories.CategoryName and Comments.CommentDate of the selected News object.
Here is my code
News news = db.News.Include(w => w.Categories)
.Include(w => w.Comments).SingleOrDefault(n => n.NewsId == Id);
Here are my Entities:
News Entity:
public partial class News
{
public News()
{
this.Categories = new HashSet<Category>();
this.Comments = new HashSet<Comment>();
}
public int NewsId { get; set; }
public string NewsTitle { get; set; }
public string NewsBody { get; set; }
public System.DateTime NewsDate { get; set; }
public string NewsImagePath { get; set; }
public virtual ICollection<Category> Categories { get; set; }
public virtual ICollection<Comment> Comments { get; set; }
}
Category Entity:
public partial class Category
{
public Category()
{
this.News = new HashSet<News>();
}
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public virtual ICollection<News> News { get; set; }
}
Comment Entity:
public partial class Comment
{
public Comment()
{
this.News = new HashSet<News>();
}
public int CommentId { get; set; }
public string CommentBody { get; set; }
public Nullable<System.DateTime> CommentDate { get; set; }
public virtual ICollection<News> News { get; set; }
}
This LINQ query should take care of it:
var query =
from news in db.News
where news.Id == Id
let categoryNames =
from category in news.Categories
select category.Name
let commentDates =
from comment in news.Comments
select comment.CommentDate
select new {
CategoryNames = categoryNames.ToList(),
CommentDates = commentDates.ToList()
};
That query is not using SelectMany, but that wouldn't help you, since then you wouldn't be able to group your categories and comments by news items. Since categories and comments are not directly connected, you'd need two SelectManys and then you'd need to cross join the results. That would obviously not be what you want.
Maybe try using the following?
var categoryNames = news.Categories.Select(c=>c.CategoryName);
var commentDates = news.Comments.Select(c=>c.CommentDate);
Note that SelectMany is used to flatten lists.For example, lets say you have collection of news matching certain search criteria, and then you use SelectMany to collect all the Categories/Comments of these news set, in a flat list.

How to edit multiple tables in MVC using ViewModel pattern

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
}
}

Display custom entity based on two class (ViewModel and Domain Model)

Hi im making a project using asp.net mvc 4.0 , with entity framework and linq...
So i have two classes.
Cliente Class:
namespace LicenciamentoMVC.Models
{
public class Cliente
{
[Key]
public int IDCliente { get; set; }
public string Nome { get; set; }
public string Morada { get; set; }
public string CPostal { get; set; }
public string Localidade { get; set; }
public string Freguesia { get; set; }
public string Conselho { get; set; }
public string Distrito { get; set; }
public string Pais { get; set; }
public string Telefone { get; set; }
public string Telemovel { get; set; }
public string Fax { get; set; }
public string Email { get; set; }
public string Nif { get; set; }
public string WWW { get; set; }
public string Observacoes { get; set; }
public int IDP { get; set; }
public int IDU { get; set; }
public DateTime TStamp { get; set; }
public int Rem { get; set; }
public String TipoCliente { get; set; }
}
public class ClienteModel
{
private static Cliente entity;
public static IQueryable<Cliente> GetListaClientes()
{
MvcApplication1Context db = new MvcApplication1Context();
var customers = from c in db.Clientes
orderby c.IDCliente descending
where c.Rem==0
select c;
return customers.AsQueryable<Cliente>();
}
}
}
and here is my Processo Class
public class Processo
{
[Key]
public int IDProcesso { get; set; }
public int IDCliente { get; set; }
public DateTime DataInserido { get; set; }
public string NumeroFactura { get; set; }
public DateTime DataFactura { get; set; }
public string Estado { get; set; }
public int IDU { get; set; }
public int Rem { get; set; }
public DateTime TStamp { get; set; }
}
Lets say i want to view the the IDprocesso and DataInserido from class Processo, and Nome from class Cliente.
My database is composed of two tables Clientes and Processos.
My dbContent Class:
public class MvcApplication1Context:DbContext
{
public MvcApplication1Context()
: base("name=MvcApplication1Context")
{
}
//protected override void OnModelCreating(DbModelBuilder modelBuilder)
//{
// modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
//}
public DbSet<Cliente> Clientes { get; set; }
public DbSet<Processo> Processos { get; set; }
}
The method GetListClientes is an iqueryable because i am using Igniteui components, in this case igGrid and i followed a tutorial that i found in the infragistics site, if there is a better way to do this, please tell me..
Back to the topic..
I didnt declare the foreign keys because of problem with contrains..
Should i create a new class with the fields that i want to see , or is there another way.
if i go with the method of create a new class for showing the data i should do something like this inside that class:
public class ProcessoClienteModel
{
private static ProcessoCliente entity;
public static IQueryable<ProcessoCliente> GetListaProcessos()
{
MvcApplication1Context db = new MvcApplication1Context();
var processos = from p in db.Processos
from c in db.Clientes
orderby p.IDProcesso descending
where p.IDCliente == c.IDCliente
where p.Rem == 0
select new { p.processoID,p.DataInserido,c.Nome} as IQueryable<ClienteModel>;
return processos;
return processos.AsQueryable<ProcessoCliente>();
}
}
Or is there a better way for doing this...
I am going through topics on internet trying to find a way..
Thanks for the help..
So i have been trying to find a way and the thing that i am trying to make is a viewmodel class, in this view model i will have the fields that i want to display, the Processo id, Data Inserido and the name of the cliente..and this class wil fetch value through linq to my domain class, in this case processo and cliente...
Am i going in the right direction???
Using the tip that Bjorn Vdkerckhove gave me, thanks, i have done this..
Create a new folder called viewmodel, and inside create a new class called ProcessoCliente.cs
The code of this class:
namespace LicenciamentoMVC.ModelsView
{
public class ProcessoCliente
{
public int IDProcesso { get; set; }
public string NomeCliente { get; set; }
public DateTime DataInserido { get; set; }
}
public class ProcessoModel
{
private static ProcessoCliente entity;
public static IQueryable<ProcessoCliente> GetListaProcessosClientes()
{
MvcApplication1Context db = new MvcApplication1Context();
var processos = (from p in db.Processos
join c in db.Clientes on p.IDCliente equals c.IDCliente
orderby p.IDProcesso descending
select new ProcessoCliente { IDProcesso = p.IDProcesso, NomeCliente = c.Nome, DataInserido = p.DataInserido});
return processos.AsQueryable<ProcessoCliente>();
}
}
}
then i create the view on the index action of controller Processo
#model IEnumerable<LicenciamentoMVC.ModelsView.ProcessoCliente>
#using Infragistics.Web.Mvc
#{
ViewBag.Title = "Index";
}
#* render of ignite ui grid *#
#( Html.Infragistics().Grid<LicenciamentoMVC.ModelsView.ProcessoCliente>()
.Caption("Processos")
.ID("grid1")
.DefaultColumnWidth("200px")
.PrimaryKey("IDProcesso")
.Columns(column =>
{
column.For(x =>x.NomeCliente).DataType("string").HeaderText("Nome do Cliente").Width("60%");
column.For(x => x.DataInserido).DataType("DateTine").HeaderText("Data de Criação do Processo").Width("40%");
column.For(x => x.IDProcesso).DataType("int").Width("0%");
})
.Features(features =>
{
features.Paging().PageSize(20).PrevPageLabelText("Previous").NextPageLabelText("NEXT");
features.Sorting().Mode(SortingMode.Single).ColumnSettings(settings =>
{
settings.ColumnSetting().ColumnKey("NomeCliente").AllowSorting(true);
});
features.Selection().MultipleSelection(false).Mode(SelectionMode.Row);
features.Filtering().Mode(FilterMode.Simple);
features.Updating()
.EnableAddRow(false)
.EnableDeleteRow(true)
.EditMode(GridEditMode.None);
})
.DataSourceUrl(Url.Action("ListarProcessos"))
.UpdateUrl(Url.Action("DeleteProcessos"))
.AutofitLastColumn(false)
.Width("100%")
.AutoGenerateColumns(false)
.DataBind()
.Render()
)
And i have this action inside ProcessoController to load the grid..
[GridDataSourceAction]
public ActionResult ListarProcessos()
{
return View(LicenciamentoMVC.ModelsView.ProcessoModel.GetListaProcessosClientes());
}
It works, but i would like to know if this is the right way to go...or there is a better way to do it..
Thanks again,..
You don't have any real relation between the objects if i understand you correctly. It all depends on how much data you need to show.
If you want to show related data, you can do this on your view with razor:
#foreach(var client in Model.Clientes)
{
<h1>#client.Name</h1>
<ul>
<li>Model.Processo.FirstOrDefault(f=> f.IDCliente == client.IDCliente).DataInserido.toString("dd-MM-yyyy")</li>
<li>.... other properties...</li>
</ul>
}

c#. EF entity sql. How to get entity with related objects?

I have made simple model for example.
public class Publisher
{
public int Id { get; set; }
public string Title { get; set; }
public Address Location { get; set; }
public virtual ICollection<Book> Books { get; set; }
}
public class Address
{
public string Country { get; set; }
public string City { get; set; }
public string Street { get; set; }
public string HouseNumber { get; set; }
}
public class Book
{
public int Id { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public int LanguageId { get; set; }
public int? PublisherId { get; set; }
}
I need to get publishers with related books. I know how to do it using linq to entities. Is it possible to solve a problem using entity sql?
public class CatalogContext : DbContext {...}
public List<Publisher> GetByCity(string city)
{
var result = new List<Publisher>();
string queryString;
queryString = String.Format(#"SELECT VALUE row(a,b)
FROM CatalogContext.Publishers AS a
join CatalogContext.Books AS b on a.Id = b.PublisherId
WHERE a.Location.City = '{0}'", city);
var rows = ((IObjectContextAdapter)_context).ObjectContext.CreateQuery<DbDataRecord>(queryString).ToList();
return ???
}
Query returns required data but it's List<DbDataRecord> - list of pairs <publisher, book>. How to translate it to list of publishers with filled navigation property "Books"?
Is it possible to write query which directly returns List<Publisher>?
you can do the following:
var result = ObjectContext.Publishers.Include("Books").Include("Locations")
.Where(c => c.Location.City = "SOME_CITY").Select(c => c);
Include - basically joins the table.
Then you can drill down to books by doing the following:
var test = result[0].Books;
Why are you using direct sql command instead of Entity Framework code style?

Categories

Resources