I know that NSFetchedResultsController does not support multiple entity. But I would like to know what is the efficient way to solve the problem below.
Let's say I have two entity: catalogue and selectedProduct. I am fetching all the entity catalogue to the user so he can select some products the task is: only propose the products in the catalogue that are not in selectedproduct.
In SQL it will be like select * from catalogue where productName not in (select productName from selectedProduct).
In think the following predicate should filter the products as you require:
fetch.predicate = NSPredicate(format:"SUBQUERY(lescourses, $lc, $lc.listedescourses == %#).#count == 0",listdescourses)
I've used SUBQUERY. In theory it could be done with NONE or NOT ANY, but I sometimes find CD doesn't parse them correctly. Note that, as per comments, the FRC will observe only the changes to TblProduits, to if you were to modify an existing TblLesCourses object to establish a relationship to listdescourses, the FRC will not (unless you redo the performFetch) recognise that the related TblProduits objects should no longer be included.
Related
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.
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.
I have a Customer Entity with a OneToMany relationship to an Invoice Entity.
In plain old sql i can do "select customer_name,customer_age,[some other fields] from customer, invoice where ... [put some filtering here]", which gets me exactly one record with the fields i need.
In JPA i use "select c from Customer c join c.invoiceCollection where ... [same filtering as above]"
This works, but i get the Customer entity with all its associated invoices.
This is nonsense, because i pull a huge amount of (invoices) data from the database, which i do not need. I need only my customer data with exactly one invoice, as specified in the where clause.
To make things worse, i have to loop over the Customer.invoiceCollection in order to find the one specific invoice needed. This costs me even more time plus it exposes my "where" clause to the middle-tier.
Question: is there a JPA select syntax which fetches exactly one record from a one-to-many relationship, as defined in the where clause?
Things tried so far:
a) lazy loading. This does not work, throws an exception whenever i try to access Customer.invoiceCollection.
Even if it worked, i'd get a Collection with some 1000 entries, which i do not need.
b) changed my jpa statement to "select c,i from Customer c join c.invoiceCollection i where ...". This returns me an array of objects, which i have to manually map to a Customer / Invoice entity.
It works, but it makes the ORM philosophy obsolete. If i perform all the mapping from relational database records/fields to java objects manually in my code, why do i need JPA?
This is one of the most infuriating things about JPA. For example, you NEED the OneToMany side if you want Customer to cascade delete Invoices. In most cases you'd like to tell Invoices to delete itself when a Customer is deleted so that Customer does not necessarily need to know about Invoice.
My suggestion for you is that you keep the OneToMany there but get the Lazy Loading working. In your code, do not access "Customer#getInvoices" directly (unless you really need all of them).
This will allow you to do queries on customers that join to invoices without loading them.
I'm guess the exception you are getting just has to do with transaction boundaries which can be easily fixed.
For a lot of these relationships I often add the OneToMany as a private instance variable but I don't create the #getter method. That way I can use it in queries, setup cascade delete, etc. but I don't provide a way to accidentally load thousands of invoices from a customer.
Oh, and for those queries where you need exactly one invoice with its associated customer you should just do the JPA query on the Invoice and then call #getCustomer on that invoice object. That will be eagerly fetched for you.
If you need exactly one invoice with the related customer, why don't you create a query simply based on Invoice?
select i from Invoice i where [same filtering..]
You should not use one-to-many relationship in this case.
One-to-many relationships are suitable for situations when objects at "many" side are logical parts of object at "one" side (e.g. relationship from Invoice to InvoiceLine).
In you case you need a unidirectional many-to-one relationship from Invoice to Customer, so that you can query it as follows:
select i from Invoice i where ...
Then you can use customer field of Invoice to access Customer or filter by its properties.
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()
};
Greetings,
Considering the Northwind sample tables Customers, Orders, and OrderDetails I would like to eager load the related entities corresponding to the tables mentioned above and yet I need ot order the child entities on the database before fetching entities.
Basic case:
var someQueryable = from customer in northwindContext.Customers.Include("Orders.OrderDetails")
select customer;
but I also need to sort Orders and OrderDetails on the database side (before fetching those entities into memory) with respect to some random column on those tables. Is it possible without some projection, like it is in T-SQL? It doesn't matter whether the solution uses e-SQL or LINQ to Entities. I searched the web but I wasn't satisfied with the answers I found since they mainly involve projecting data to some anonymous type and then re-query that anonymous type to get the child entities in the order you like. Also using CreateSourceQuery() doesn't seem to be an option for me since I need to get the data as it is on the database side, with eager loading but just by ordering child entities. That is I want to do the "ORDER BY" before executing any query and then fetch the entities in the order I'd like. Thanks in advance for any guidance. As a personal note, please excuse the direct language since I am kinda pissed at Microsoft for releasing the EF in such an immature shape even compared to Linq to SQL (which they seem to be getting away slowly). I hope this EF thingie will get much better and without significant bugs in the release version of .NET FX 4.0.
Actually I have Tip that addresses exactly this issue.
Sorting of related entities is not 'supported', but using the projection approach Craig shows AND relying on something called 'Relationship Fixup' you can get something very similar working:
If you do this:
var projection = from c in ctx.Customers
select new {
Customer = c,
Orders = c.Orders.OrderByDescending(
o => o.OrderDate
)
};
foreach(var anon in projection )
{
anon.Orders //is sorted (because of the projection)
anon.Customer.Orders // is sorted too! because of relationship fixup
}
Which means if you do this:
var customers = projection.AsEnumerable().Select(x => x.Customer);
you will have customers that have sorted orders!
See the tip for more info.
Hope this helps
Alex
You are confusing two different problems. The first is how to materialize entities in the database, the second is how to retrieve an ordered list. The EntityCollection type is not an ordered list. In your example, customer.Orders is an EntityCollection.
On the other hand, if you want to get a list in a particular order, you can certainly do that; it just can't be in a property of type EntityCollection. For example:
from c in northwindContext.Customers
orderby c.SomeField
select new {
Name = c.Name,
Orders = from o in c.Orders
orderby c.SomeField
select new {
SomeField = c.SomeField
}
}
Note that there is no call to Include. Because I am projecting, it is unnecessary.
The Entity Framework may not work in the way you expect, coming from a LINQ to SQL background, but it does work. Be careful about condemning it before you understand it; deciding that it doesn't work will prevent you from learning how it does work.
Thank you both. I understand that I can use projection to achieve what I wanted but I thought there might be an easy way to do it since in T-SQL world it's perfectly possible with a few nested queries (or joins) and order bys. On the other hand seperation of concerns sounds reasonable and we are in the entity domain now so I will use the way you two both recommended though I have to admit this is easier and cleaner to achieve in LINQ to SQL by using AssociateWith.
Kind regards.