Reputation: 301
I wonder if I could get some help with the following. I'm retrieving set of data as follows using EF.
var booking = this.GetDbSet<Booking>().Include(c => c.BookingProducts.Select(d => d.Product.PrinterProducts.Select(e => e.ProductPrices))).Single(c => c.BookingId == bookingId)
Within a PrinterProduct there is a foreign key PrinterId for an additional entity Printer. With the Booking Entity I also have PrinterId also linked by foreign key to the additonal entity Printer.
What I'm hoping to do is retrieve only the PrinterProduct relating to the PrinterId held in the booking entity rather that all the PrinterProducts as in my code. I've tried to use Join but have tied myself in knots!
Grateful for any help!
Edit:
Object structure:
public class Booking
{
public Guid BookingId { get; set; }
public string BookingName { get; set; }
public Printer Printer { get; set; }
public IEnumerable<BookingProduct> BookingProducts { get; set; }
}
public class BookingProduct
{
public int BookingProductId { get; set; }
public Booking Booking { get; set; }
public Product Product { get; set; }
}
public class Product
{
public int ProductId { get; set; }
public string ProductName { get; set; }
public IEnumerable<PrinterProduct> PrinterProducts { get; set; }
}
public class PrinterProduct
{
public int PrinterProductId { get; set; }
public Product Product { get; set; }
public Printer Printer { get; set; }
public IEnumerable<ProductPrice> ProductPrices { get; set; }
}
public class ProductPrice
{
public int ProductPriceId { get; set; }
public PrinterProduct PrinterProduct { get; set; }
public decimal Price { get; set; }
}
public class Printer
{
public int PrinterId { get; set; }
public string PrinterName { get; set; }
public IEnumerable<Booking> Bookings { get; set; }
public IEnumerable<PrinterProduct> PrinterProducts { get; set; }
}
Upvotes: 2
Views: 166
Reputation: 13803
Given the newly added class structures in your question, I hope I can clear it up now.
From what I see, Bookings
and Products
have a many-to-many relation (where BookingProduct
is used as the connection). The same is true for Product
and Printer
(where PrinterProduct
is used as the connection).
From what I understand, you are trying to get from a singular Booking
item to a singular PrinterProduct
. I don't see any efficient way to do this without introducing the possibility of inconsistency with your data. You're expecting some Lists to return you one result. If it's only one result, why is it a List in the first place?
Booking
. You take its BookingProducts
. Now you have many items.Product
from each individual BookingProduct
. If all BookingProducts
have the same product, you're in luck and will only have a List<Product>
with a single Product
in it. However, there is nothing stopping the system from return many different products, so we are to assume that you now hold a List
of several Products
Product
in the list, you now take all of its PrinterProducts
. You now hold many PrinterProducts
of many Products
.As you see, you end up with a whole list of items, not just the singular entity you're expecting.
Bookings
, Products
and Printers
are all connected to eachother individually, like a triangle. I have seen scenarios where that is correct, but nine times out of ten, this is not what you want; and only leads to possible data inconsistency.
Look at it this way: Is it ever possible for the Product
to have a Printer
other than the Printer
that is already related to the Booking
? If not, then why would you have two relations? This only introduces the possibility that Booking.Printer
is not the same as PrinterProduct.Printer
.
Your relational model is set up to yield many results, but I think you expect a single result in some places. I would suggest taking another look at your data model because it does not reflect the types of operation you wish to perform on it. Change the many-to-many relations to one-to-many where applicable, and you should be able to traverse your data model in a more logical fashion, akin to the answer I provided in my previous answer.
Upvotes: 1
Reputation: 13803
If you've set up navigational properties, you can just browse to it:
var myBooking = ... //A single Booking, don't know how you retrieve it in your case.
var myPrinter = myBooking.Printer; //the Printer that is related to the Booking.
var myPrintproducts = myPrinter.PrintProducts; //The products that are related to the printer.
You don't need to keep nesting select statements, that only creates unnecessary confusion and overhead cost. Keep in mind that you need to do this while in scope of the db context. Every time you try to access a property, EF will fill in the needed variables from the database. As long as there is an open db connection, it works.
Edit
If you really need to optimize this, you can use a Select statement. But you only need a single one. For example:
var myPrintproducts = db.Bookings.Single( x => x.ID == some_id_variable ).Select( x => x.Printer.PrintProducts);
But unless you have a very strict performance requirement, it seems better for code readability to just browse to it.
Upvotes: 1