I am new to MVC and this is my function. There are three tables (Order, OrderNotes, Notes), ID is their primary key. One Order can have many Notes, the table OrderNotes has foreign key OrderID(from Booking table) and NotesID(from Notes table). I want to have a Order Edit page to display individual Order (FirstName, LastName), also display a list of its Notes. Here is my DB structure:
Booking table:
{ID,
FirstName,
LastName
}
BookingNotes table:
{ID,
BookingID,
NotesID
}
Notes table:
{ID,
NoteName,
StatusID
}
So how can I implement the list of Notes since it's from multiple tables? It will be able to Create New Note, Delete existing Note in the list row record, not Edit. Linq used in DB query. Thanks.
It would be a better idea to have only 2 tables:
public class Book
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
// Navigational properties
public virtual List<Note> Notes { get; set; }
}
public class Note
{
public int ID { get; set; }
public int BookID { get; set; }
public string NoteName { get; set; }
public int StatusID { get; set; }
// Navigational properties
public virtual Book Book { get; set; }
public virtual Status Status { get; set; }
}
A third table is useful when you want to reuse the same Note for a different booking. However i think this is not the case.
So to retrieve data for your context make sure you have the DbSet<Book>
public class ApplicationDbContext : DbContext
{
public virtual DbSet<Book> Bookings { get; set; }
}
In your controller (or better in a repository class):
var BookingID = 10; // this is parameter passed to the function
var myBooking = this.dbContext.Bookings
.Include(p => p.Notes)
.ThenInclude(p => p.Status)
.FirstOrDefault(p => p.ID == BookingID);
Map the retrieved booking to a ViewModel, pass it to the View and you're good to go.
Related
I have joined and grouped 2 databases using linq in my controller, and now I need to parse it to the view. I know, I gonna need a ViewModel to do it, but I have no clue what to put in it, to make it work.
My Linq query in the controller looks like this:
var energyUsageViewModel =
from e in applicationDbContext
join u in _context.UsagesPerMonth on e.Id equals u.EnergyUsageId into u2
group u2 by new { Year = e.Year }
into u3
select u3.ToList();
return View(energyUsageViewModel);
In short what the linq query does is taking the "year" from table "e" joining it with table "u" which contains the energy usage per month, which I am gonna use to make a table in my view, which displays the year and usage per month in one row.
And currently my ViewModel looks like this (obviously not working):
public class EnergyUsageViewModel
{
public IEnumerable<UsagePerMonth> UsagePerMonthVm { get; set; }
}
The view takes a model of:
#model IEnumerable<Jullerup.Models.EnergyUsageViewModel>
I have tried to modify the ViewModel to take u3, but haven't succeeded.
I get the following invalid operation exception:
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'System.Linq.Enumerable+SelectEnumerableIterator2[System.Linq.IGrouping2[<>f__AnonymousType101[System.String],System.Collections.Generic.IEnumerable1[Jullerup.Models.UsagePerMonth]],System.Collections.Generic.List1[System.Collections.Generic.IEnumerable1[Jullerup.Models.UsagePerMonth]]]', but this ViewDataDictionary instance requires a model item of type 'System.Collections.Generic.IEnumerable`1[Jullerup.Models.EnergyUsageViewModel]'.
How do I edit my ViewModel to handle u3?
Update:
I'm working with 3 classes.
Customer class:
public class Customer
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
//Navigation Prop
public ICollection<EnergyUsage>? energyUsage { get; set; }
}
EnergyUsage class:
public class EnergyUsage
{
public int Id { get; set; }
public int CustomerID { get; set; }
public DateTime Date { get; set; }
public int YearlyHeatUsage { get; private set; }
public List<UsagePerMonth> UsagePerYear { get; set; }
//Navigation Prop
public Customer? Customer { get; set; }
}
UsagePerMonth class:
public class UsagePerMonth
{
public int Id { get; set; }
public MonthEnum Month { get; set; }
public int Usage { get; set; }
public int HeatUsage { get; private set; }
public string EnergyType { get; set; }
private EnergyMeasurement energyType { get; set; }
public int EnergyUsageId { get; set; }
}
In the database Customer.Id (PK) has a one to many relationship to EnergyUsage.CustomerId (FK) and EnergyUsage.Id (PK) has a one to many relationship to UsagePerMonth.EnergyUsageId (FK).
What I am trying to do, is to get an object/list something I can use in the view to display all instances of UsagePerMonth grouped by Customer.Year for a certain Customer.Id.
I read a post from EF with MVC.The example used three tables with 1-to-many relationships. And with StudendId as the foreign key set up, I can directly call Model.Enrollments(model is of Student type ) in the view.
I'd like to know How could I set up a many-to-many relationship with two tables.
With a beginning:
public class Post
{
public int Id
{ get; set; }
public int CategoryId
{ get; set; }
public string Title
{ get; set; }
public string ShortDescription
{ get; set; }
public string Description
{ get; set; }
public virtual ICollection<Tag> Tags
{ get; set; }
}
public class Tag
{
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public int TagId
{ get; set; }
public string Name
{ get; set; }
public string UrlSlug
{ get; set; }
public string Description
{ get; set; }
public virtual ICollection<Post> Posts
{ get; set; }
}
I'd like to call Model.Tags to get all the Tags related to a Post or call Model.Posts to get all the Posts belong to a Tag in the view. I guess I need a class something like
public class TagPost
{
public int TagId{get;set;}
public int PostId{get;set;}
}
But It looks like TagId and PostId both are foreign keys? I am not sure what to do.
Reading:
var post1 = dbContext.Post.FirstOrDefault(x => x.PostId ==1);
var tags = post1.Tags();
Inserting:
// Create a New Post Entity
var post = new Post();
// Assign it you values either from ViewModel or
post.Title ="ManyToMany";
// Create your list of tags related to Post
post.Tags = new List<Tags>();
// Add a Tag from Database to this List where TagId == 1
post.Tags.Add(dbContext.Tags.First(s => s.TagId == 1));
// save Changes
dbContext.SaveChanges();
after save Changes you will see that in you Many-to-Many Mappings table there is a new Record with
PostId = 2 // Considering you have PostId == 1 already in DB
TagId = 1 // Tag you added before dbContext.SaveChanges()
I have two tables. There is one-to-many relationship between these tables.I want to select Company table and BankAccount List table (for appropriate CompanyID).
How can I do it with Linq-to-Sql?
public class Company
{
// My Fields
[Key]
public Guid ID { get; set; }
public string FullName { get; set; }
// My virtual properties FOR relationships(one-to-one,one-to-many etc.).
public virtual List<BankAccount> BankAccounts { get; set; }
}
and
public class BankAccount
{
// My Fields
//[ScaffoldColumn(false)]
[Key]
public Guid ID { get; set; }
[ForeignKey("Companies")]
public Nullable<Guid> CompanyID { get; set; }
public string BankName { get; set; }
// My virtual properties FOR relationships(one-to-one,one-to-many etc.).
public virtual Company Company { get; set; }
}
I write this as follow, but I didn't like it
List<List<BankAccount>> bankaccounts = new List<List<BankAccount>>();
foreach (var comp in companyRepository.Companies)
{
List<BankAccount> banks = new List<BankAccount>();
foreach (var bank in bankRepository.BankAccounts)
{
if (comp.ID == bank.CompanyID)
{
banks.Add(bank);
}
}
bankaccounts.Add(banks);
banks = new List<BankAccount>();
}
I think the following will yield the same result.
var bankaccounts = companyRepository.Companies.Select(c => c.BankAccounts)
.ToList();
If you are using entity framework, you can eagerload the 'BankAccounts' property to minimize DB calls.
Hope this helps.
I have 2 Models a customer table and a product table. I am pretty new to MVC and I have created a model and I have the auto generated controller and views for details, delete, create... etc...
My models are:
[Table("Product")]
public class Product
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int ProductId { get; set; }
public decimal Price { get; set; }
public int CustomerId { get; set; }
}
[Table("Customer")]
public class Customer
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int CustomerId { get; set; }
public string Name { get; set; }
}
My question is, how do I display a list of the products based on the customer name. Obviously they are joined by CustomerId but how do I combine controllers. So I want to display some data based on data from another table.
You need to add a Navigation Property to Customer.
[Table("Customer")]
public class Customer
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int CustomerId { get; set; }
public string Name { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
Then you can use that to access the products for a customer.
public ActionResult ProductsByCustomer(string id)
{
// Find the customer by name
var customer = dbContext.Customer.First(c => c.Name == id);
// Get the customers products
var customersProducts = customer.Products;
// Send products to the View to be rendered
return View(customersProducts);
}
i have the following tables which i want to map with EF 4.1 Code First:
Items - An item which can have a number of categories
ItemCategories - The relation table to map the many-to-many relationship of Items<->Categories
Category - An Category, categories are a tree of categories, ParentId is self referencing
CategoryLink - This table contains the edges of the tree
The question is how can I create the EF code first mapping for my entity classes so that I can use the Categories collection property on Item while being able to use all my tables inside a query (especially a join over the relation table) like this:
//searchIds contains a list of category guids to be searched for inside the category tree
var query = from item in db.Items
join itemCategory in db.ItemCategories on item.Id equals itemCategory.ItemId
join category in db.Categories on itemCategory.CategoryId equals category.Id
join categoryLink in db.CategoryLinks on category.Id equals categoryLink.ChildId
where searchIds.Contains(categoryLink.ParentId)
select item;
Here are the entity classes with DbContext(without the mappings)
class TestContext : DbContext
{
public DbSet<Category> Categories { get; set; }
public DbSet<Item> Items { get; set; }
public DbSet<ItemCategory> ItemCategories { get; set; }
public DbSet<CategoryLink> CategoryLinks { get; set; }
}
public class Item
{
public Guid Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Category> Categories { get; set; }
}
public class ItemCategory
{
public Guid ItemId { get; set; }
public Guid CategoryId { get; set; }
}
public class Category
{
public Guid Id { get; set; }
public Guid? ParentId { get; set; }
public virtual Category Parent { get; set; }
public string Name { get; set; }
}
public class CategoryLink
{
public Guid ParentId { get; set; }
public Guid ChildId { get; set; }
public virtual Category Parent { get; set; }
public virtual Category Child { get; set; }
}
Thanks
I've only played around a bit with code first not sure if this may help. but the below posts show how to create bridge tables and work around for many-to-many issue with EF4.1 code first.
How to perform CRUD with Entity Framework Code-First?
also
Forcing a bridge/join table to become a many to many relationship in EF4