Entity Framework - best practice to get count - entity-framework

I have a Customer table and another Orders table. Each Customer can have many orders (One to many relationship).
I want to get a Customer object and from it get how many orders he has (the actual order data is not relevant at this point). So as I see it I have 2 options:
create a view with another OrdersCount field - and that will be another object in my system.
in my app, when I need the count get the Customer.Orders.Count - but for my understanding that will cause an extra query to run and pull all the orders from the database to that collection.
Is there a correct way to do such thing?
Thanks

You do need a new type, but you don't need to recreate all relevant properties.
from c in context.Customers
// where ...
select new {
Customer = c,
OrderCount = c.Orders.Count()
}
Update code that looks for e.g. the Name property of an item in the result, to look for Customer.Name.

Related

Selecting columns from different entities

I don't know whether I should be drawing parallels, but unfortunately, that's the only way I can express my issue.
In SQL, suppose we have two tables:
Employee with columns Employee ID, Employee Name, Dept. ID
Deptartment with columns Dept. ID, Dept Name
The Dept ID. in the Employee table is a foreign key with that in the Department table.
Now suppose I want to fetch the following columns:
Employee ID, Employee Name, Department Name
using a SQL such as:
SELECT A.EMPLOYEE_ID, A.EMPLOYEE_NAME, B.DEPT_NAME
FROM EMPLOYEE A, DEPARTMENT B
WHERE A.DEPT_ID = B.DEPT_ID
How would one do this using Core Data in Swift? I guess I'm getting confused by only seeing references to
NSFetchRequest(entityName: entityName)
where the entityName refers to a single entity (table in relational DB lingo)
I'd really appreciate any pointers or examples that can help me clear my doubts.
Thanks
It is certainly possible to create a fetch request that is equivalent to your SQL query. More complex queries can be difficult if not impossible to achieve with a single fetch request. But I recommend trying NOT to draw parallels between CoreData and SQL, at least until you have got to grips with how it works.
To take your example, in the CoreData view of the world, Employee would be an entity with a relationship to another entity, Department. A fetch request based on the Employee entity will return an array of Employee objects, and (assuming you create subclasses of NSManagedObject for each entity) you can access the attributes with simple dot notation:
let employeeName = myEmployeeObject.employeeName
But you can use the same notation to traverse relationships equally easily:
let departmentName = myEmployeeObject.department.departmentName
You don't need to worry about joins, etc; CoreData handles that for you.
Now, suppose you try to do it "the SQL way". You can construct a fetch request based on the Employee entity, but specify "properties to fetch" which likewise traverse the relationship:
let fetch = NSFetchRequest(entity:"Employee")
fetch.propertiesToFetch = ["employeeID", "employeeName", "department.departmentName"]
For this to work, you would need to specify the "resultType" for the fetch request to be DictionaryResultType:
fetch.resultType = .DictionaryResultType
The results from this query would be an array of dictionaries containing the relevant keys and values. But the link with the underlying objects is lost. If you subsequently want to access any details from the relevant Department (or even the Employee), you would have to run a new fetch to get the object itself.

DDD and Entity Framework: Pulling children from aggregate root

This one is driving me nuts!
For simplicity, I'm not gonna put up the entire code that is used for our DDD but simply expose what I've tried and explain what isn't working.
I have a simple database structure:
Products (holds product data)
Orders (holds entered orders)
OrderProducts (ref table between Orders and Product)
I have an Order aggregate root and I want to pull out the product count of one simple Order.
I fetch my Order by id which results in an EF lambda:
var order = _orderRepository.Get(orderId);
Then, I try to pull the count of products in that order using:
var count = order.OrderProducts.Count();
This line chokes up when an order has A LOT a records because, it's fetching all of them. Fine.
So, I'm refining it a bit by adding some filters to the products I want to count from within my order.
A product has a couple of properties which include a type (so, there's a type ID).
So, now I'm trying this:
//This is trimming down my results to about a dozen products)
var count = order.OrderProduct
.Where(op=>op.Product.TypeId == 2)
.Count();
If I use Linqpad to see what kind of SQL is generated, to my surprise, it's still loading ALL the OrderProducts from this order!
How can I force it to apply the filter in the query directly?
It's loading all of them because once you touch the navigation property (i.e. order.OrderProducts) eager loading kicks in and loads all of them (i.e. even the ones that you don't want). Your only option to reduce that would be to query the database itself given the orderID. Maybe something like:
_orderProductRepository.Where(p => p.OrderID == orderId && p.Product.TypeID == 2);

Entity Framework, Computed Entity Field

Is it possible to include a computed field in an EF entity? Example, lets say I have a shop selling products, and the products are grouped into categories.
When the list of categories is displayed for editing to the administrator of the shop I wish to list the number of products in each category as part of the list.
In NHibernate I would use a formula e.g.
<property name="Products" formula="dbo.Category_NumProducts(id)" />
I can't work out if something similar is possible for EF. I know I could make a category view and map this to a second entity but that seems wrong as its almost a complete duplication.
EDIT: If this isn't possible in EF, then what is the best way to accomplish this?
Unfortunately if your Category table doesn't have this as computed column you will not be able to map it without creating second entity - it leads to database view, defining query in EDMX or perhaps Query view in EDMX (but Query view may not work because you require aggregate function to be computed).
Edit:
IMHO the simplest solution (and also the best) is simply creating a ViewModel (some non mapped class) and use projection in Linq query:
var query = from c in context.Categories
where ...
select new CategoryView {
Id = c.Id,
Name = c.Name,
...
Products = c.Products.Count()
};

Handling Many to Many - Entity Framework

I have an MVC app I am building as a learning project. I have a table with Payees, and a table with Categories. Certain Payees can make transactions of certain categories. For example, Payee A can make payments to Categories A, B and C. Payee B can maybe payments to categories B, C and D.
So, I have a PayeeCategory linking table, with a PayeeId and a CategoryId.
So see the categories the payee can make transactions against, it's a simple Select from PayeeCategory where PayeeId = this.PayeeId. And I join to the Category table to get the category names.
In the view, when I edit a Payee, I need to display a list of all categories, and and allow the user to select or unselect the categories that the current Payee is associated to.
So, in my ViewModel, I'd have a list of categorySelectableItems, which has maybe the CategoryId, the DisplayName and a Selected boolean field. To get the data, I need to Select from Categories, LEFT JOIN PayeeCategory, and where PayeeCategoryId is null, set the Selected to false, else true.
How would I do that ina single Linq statement?
Then, when the data comes back... how would I save the data? Would I have to delete all the relationships, and then re-add them based on the List<> values I get back?
Hope someone can guide me.
This was answered in a different question.
Linq query assistance

Many to many relationship with ADO.NET Entity Data Model

I've created many-to-many relationship with ADO.NET with extra order fields in the middle table.
So I have...
Customers
-customer_id
-customer_name
Orders
-order_id
Customers_to_Orders
-customer_id
-order_id
-seq
And now I don't really know how to add new orders to customers with specyfing order, any suggestions?
Create the order first.
Get the ID back for the order.
Then, create the link from the customer to the order.
you add the order to orders table first, and then add it to customer_to_orders preferably in one transaction.
if you're worried about the seq - it can be either identity or you can calculate "next seq" by querying customers_to_orders before adding new data.