I'm trying to build a full-stack car rental project. I've got CarImage and Car, CarDetailDto classes, and relative Business/Data operations. I'm sending CarDetailDto properties to the Angular project, not Car class properties. I wrote a Linq in order to send CarDetailDto values to the front-end project. I try to show CarDetailDto values on a component that's called CarDetailComponent.
Here are my classes.
Car
public class Car:IEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid CarId { get; set; }
[ForeignKey("Brand")]
public Guid BrandId { get; set; }
[ForeignKey("Color")]
public Guid ColorId { get; set; }
public int ModelYear { get; set; }
public decimal DailyPrice { get; set; }
public string Description { get; set;}
}
CarImage
public class CarImage : IEntity //no naked class principle.
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid CarImageId { get; set; }
[ForeignKey("Car")]
public Guid CarId { get; set; }
public string ImagePath { get; set; }
public DateTime Date { get; set; }
}
CarDetailDto
public class CarDetailDto:IDto
{
public Guid CarId { get; set; }
public string BrandName { get; set; }
public Guid BrandId { get; set; }
public Guid ColorId { get; set; }
public List <string> ImagePaths { get; set; }
public ImagePath {get; set;}
public string ColorName { get; set; }
public int ModelYear { get; set; }
public decimal DailyPrice { get; set; }
public string Description { get; set; }
}
The Linq that I wrote to send CarDetailDto values to the Angular project through the WebAPI.
public class EfCarDal:EfEntityRepositoryBase<Car, ReCapDBContext>, ICarDal
{
public async Task<List<CarDetailDto>> GetCarDetails()
{
using(ReCapDBContext context = new ReCapDBContext())
{
var allDetails = await (
from c in context.Cars
join b in context.Brands
on c.BrandId equals b.BrandId
join col in context.Colors
on c.ColorId equals col.ColorId
join Imp in context.CarImages
on c.CarId equals Imp.CarId
select new CarDetailDto
{
CarId = c.CarId,
BrandName = b.BrandName,
ColorName = col.ColorName,
DailyPrice = c.DailyPrice,
Description = c.Description,
ModelYear = c.ModelYear,
BrandId = c.BrandId,
ColorId = c.ColorId,
ImagePath = Imp.ImagePath
}).ToListAsync();
return allDetails; //return queryable to list.
}
}
}
The GetCarDetails() function that I'm using in my Business Layer where I'm calling the linq above.
public async Task<IDataResult<List<CarDetailDto>>> GetCarDetails()
{
var result = await _carDal.GetCarDetails();
return new SuccessDataResult<List<CarDetailDto>>(result, Messages.CarDetails);
}
I'm trying to fetch photos that have the same CarId in Linq query as you can see above. Problem with the function above is: it brings the same CarDetail object repeatedly whenever it finds a match between CarImage & Car objects. Only the ID value of the CarDetailDto object changes.
GetCarDetails() / Swagger
What I'm trying to do is: create a List, put the CarImages with the same CarId in the same List and send the List to the Angular project. I don't want GetCarDetails() function to bring the same CarID for each CarImageId.
How can I do this?
What I've tried:
Tried to create a List in CarDetailDto object and add values to the list in the Linq above.
Related
I have two objects
public class Card : IEntity
{
public Guid Id { get; set; }
public string Title { get; set; }
public string BackgroundColour { get; set; }
public string Texture { get; set; }
public List<Guid> Category { get; set; }
public string Notes { get; set; }
}
and
public class Category : IEntity
{
public Guid Id { get; set; }
public string Name { get; set; }
public Guid Parent { get; set; }
}
What I would like to do is, using the Couchbase SDK, join these two objects together (Card.Category => Category.Id) in one database hit (Like a classic SQL Stored Procedure that brings me back all the data to populate both objects), but all of the (examples I found have it from id => id rather than a List of Ids (Many) to (one) id.
An example of something I tried to do...
var query = from card in context.Query<Card>()
from categoryId in card.Category.Ids
join category in context.Query<Category>()
on categoryId equals category.Id
select new CardView { Id = card.Id, Categories = category};
I want a lambda expression, that when i call a Company from database with id 1030 to bring me Companys info, a list with all the cars that company has and a list of all images that related to each car (each car has 4 images).
Structure of my classes:
public partial class Companies
{
public int CompanyId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Tel { get; set; }
public string Logo { get; set; }
public int? Owner { get; set; }
public int? Address { get; set; }
public int? Publish { get; set; }
public ICollection<Cars> Cars { get; set; }
}
public partial class Cars
{
public int CarId { get; set; }
public string Manufacturer { get; set; }
public string Model { get; set; }
public string Year { get; set; }
public string Description { get; set; }
public decimal? Price { get; set; }
public int? CarCatId { get; set; }
public int? CompanyId { get; set; }
public int? CharacteristicId { get; set; }
public ICollection<CarImages> CarImages { get; set; }
}
public partial class CarImages
{
public int CarImagesId { get; set; }
public string Image { get; set; }
public int? CarId { get; set; }
public Cars Car { get; set; }
}
As you can see in Company class, I have a reference to Cars class as ICollection, and the same thing in Cars class with CarImages.
I've try lot of things including those:
var compInfo = _context.Companies.SelectMany(cr => cr.Cars.SelectMany(i =>i.CarImages.Where(car => car.CarId == car.Car.CarId))).ToList();
var compInfo2 = _context.Companies.Include(a => a.AddressNavigation).Include(cr =>cr.Cars.).FirstOrDefault(c => c.CompanyId == id);
The 2nd brings me the info of company (and it's address) and the list of the cars (which is the half success) but not the images..
The 1st just brings me a list all the info of images table.
I found the solution.
//Get the Company with id == 1030.
var x = _context.Companies.Include(a => a.AddressNavigation).Include(c => c.Cars).Where(c => c.CompanyId == id).FirstOrDefault();
//Get the Car ICollection and include the CarImages ICollection depending on CompanyID.
var y = _context.Cars.Include(img => img.CarImages).Where(cr => cr.CompanyId == x.CompanyId).ToList();
//Now each Car in our Cars list has a list of CarImages related to each car. Finaly pass our data to our Company var(x) and send it to View.
x.Cars = y;
return View(x);
I have 2 tables in my MVC 5 application
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime? Birthdate { get; set; }
}
public class Movie
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime ReleaseDate { get; set; }
}
And joint table Rentals for many-to-many relationship
public class Rental
{
public int Id { get; set; }
[Required]
public Customer Customer { get; set; }
[Required]
public Movie Movie { get; set; }
public DateTime? DateReturned { get; set; }
}
Rental table looks like this when populated (just IDs from both Movie and Customer PKs):
Table Rental
How to select all records (just lets say customer name and all his movies) into one table from those 2 tables (or one joint Rental) in my HomeController to View?
Add navigation property (ICollection<Rental> Rentals) for Customer entity to represent Rentals entities.
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime? Birthdate { get; set; }
public ICollection<Rental> Rentals { get; set; }
}
And query per customer for all movies;
var result = dbo.Customers.Select(x => new CustomerDto
{
Name = x.Name,
Movies = x.Rentals.Select(k => k.Movie)
});
I am building a Code-First, Many-To-Many relationship between my ApplicationUser class and a Lesson class. When the model is created, Entity Framework builds the two tables and the intersecting pivot table. However, neither table seems to take in data from the pivot table (LessonApplicationUsers). Both List variables do not seem to hold either the list of Students or the list of Lessons. Both entities i'm trying to marry up already exist in the database
ApplicationUser class
public class ApplicationUser : IdentityUser
{
public string Address { get; set; }
public int? Age { get; set; }
public ClassLevel? ClassLevel { get; set; }
public string FirstName { get; set; }
public int? Height { get; set; }
public string LastName { get; set; }
public string MobileNumber { get; set; }
public string Postcode { get; set; }
public string Town { get; set; }
public int? Weight { get; set; }
public ApplicationUser()
{
Lessons = new List<Lesson>();
}
public ICollection<Lesson> Lessons { get; set; }
}
Lesson Class
public class Lesson
{
[Key]
public int LessonID { get; set; }
public LessonType ClassType { get; set; }
public ClassLevel? ClassLevel { get; set; }
public DateTime ClassStartDate { get; set; }
public DateTime ClassEndDate { get; set; }
public float ClassCost { get; set; }
public int? InstructorID { get; set; }
public Lesson()
{
Students = new List<ApplicationUser>();
}
public ICollection<ApplicationUser> Students { get; set; }
public enum LessonType {Group,Private}
}
My DBContext
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public DbSet<Lesson> Lessons { get; set; }
public DbSet<ApplyViewModel> Applications { get; set; }
And finally, the code i'm using to add in the pivot table data. This is activated when the user presses a button on the booking form.
public ActionResult BookUser()
{
//Gather required variables
ApplicationUser user = db.Users.First(i => i.UserName == User.Identity.Name);
int classID = int.Parse(Request.Form["classID"]);
using (db)
{
var editedLesson = db.Lessons.Single(s => s.LessonID == classID);
db.Lessons.Attach(editedLesson);
var editedUser = db.Users.Single(s => s.Id == user.Id);
db.Users.Attach(editedUser);
editedLesson.Students.Add(editedUser);
db.SaveChanges();
}
return View("Index");
When I try and run it, when i press my book button, it runs through the code and executes. checking the database it has indeed inserted the key values into the pivot table. When i load the model of the lesson to view its details, the Student attribute has a count of 0. I've been at this for days and i've got the feeling i'm missing something kickself simple....but i've gone over it a dozen times and can't see what i'm doing wrong...
Mark your lists with virtual to enable lazy loading. Also is not required to initialize the lists Lessons = new List<Lesson>();
Below is a POCO class i set up with Entity Framework Code first. How can i Query my database so that I can return all brands of a specific category?
Example: You have a list of categories and you click on one. It shows all brands of products available under that category.
I don't know if my classes are set up correctly to do this.
public class Product
{
[Key,ScaffoldColumn(false)]
public int ProductID { get; set; }
public string ProductName { get; set; }
public int? CategoryID { get; set; }
public virtual Category Category { get; set; }
public int? BrandID { get; set; }
public virtual Brand Brand { get; set; }
}
public class Brand
{
[ScaffoldColumn(false)]
public int BrandID { get; set; }
public string BrandName { get; set; }
}
public class Category
{
[ScaffoldColumn(false)]
public int CategoryID { get; set; }
public string CategoryName { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
What about
context.Products.
Where(p => p.Category.CategoryID == categoryToFind).Select(p => p.Brand);
or
var brands = context.Products.
Where(p => p.Category.CategoryID == categoryToFind).
Select(p => p.Brand.BrandName).Distinct().ToList();
if you just need brand names.