Why does "select many" on query syntax not work with join - entity-framework

An Invoice has many products and a product can have many X (X shall not be important here)
var query = from i in invoices
join prod in i.products on i.id equals prod.InvoiceId
select new MyClass{ Id = i.id, more props }
Why does the join not work?
I get the error that "i.product" The "i" here does not exist in the current context.

join is for when you have two separate collections, where you want to compare some properties of the various elements of those collections. You can use it when you have a separate unfiltered collection of products, and you want to find products that match on invoice ID. For instance, you might use it if you didn't define any navigation properties.
That's not what you're after here: you do have a navigation property, and by using that, Entity Framework will have set up things so that i.products only contains the matching products. You don't need to link on invoice ID manually.
var query = from i in invoices
from prod in i.products
select ...;

Related

JPQL query: Item that belongs to multiple categories

Having an entity Items that have a collection field called categories, I need to find items that belong at least to two specific categories, but I cant find the way to build the correct JPQL query.
#Entity
public class Items {
#ManyToMany (fetch = FetchType.EAGER)
private List<Category> categories;
}
I can find an item that have one category:
SELECT i FROM Item i WHERE :cat MEMBER OF item.categories
I can select items with any of several categories:
SELECT i FROM Item i WHERE :cat1 MEMBER OF item.categories OR :cat MEMBER OF item.categories
But when I try to select for items that have at least two specific categories, the following query gets no items:
SELECT i FROM Item i WHERE :cat1 MEMBER OF item.categories AND :cat2 MEMBER OF item.categories
Which is the correct way to do that?
Best regards,
Pablo.
That problem happened to me with ObjectDB.
I have contacted them too, and this was the answer:
This seems to be the result of how JPQL queries are converted into SQL
like syntax before executing. MEMBER OF is implemented using JOIN with
a new synthetic variable for iteration over the collection. In your
query item.categories appears twice, but the same synthetic variable for
iterating over that collection is used for both occurrences, and that
variable cannot match both sides of the AND with the same value.
Possibly we may have to use separate iteration per MEMBER OF as the
results as demonstrated by your post seem unacceptable (although JQPL
itself has strange behaviour in some known cases due to the conversion
to JOIN). However, using separate variables may sometimes make the
query more complex and slow unnecessarily (e.g. for the OR query in
your post), so any change requires careful planning.
As a quick solution, you may replace AND of MEMBER OF with 2 explicit
JOIN variables for iteration over the collection with 2 independent
variables.
So, the solution is to use the following query:
SELECT DISTINCT item
FROM Item item JOIN item.categories cat1 JOIN item.categories cat2
WHERE cat1 = :cat1 AND cat2 = :cat2
I don't know if this a problem only for this specific JPA implementation (ObjectDB).
Anyway, if anybody has a similar problem, I hope that this post can help.

Whats the best way to join two tables with no database relationship using EF?

Ok, lets say you have two tables: Order and OrderLine and for some reason they do not have a foreign key relationship in the database (it's an example, live with it). Now, you want to join these two tables using Entity Framework and you cook up something like this:
using (var model = new Model())
{
var orders = from order in model.Order
join orderline in model.OrderLine on order.Id equals orderline.OrderId into orderlines
from ol in orderlines.DefaultIfEmpty()
select new {order = order, orderlines = orderlines};
}
Now, the above will produce orders and orderlines, left-joined and all, but it has numerous issues:
It's plain ugly
It returns an anonymous type
It returns multiple instances of the same order and I you have to do Distinct() on the client side because orders.Distinct() fails.
What I am looking for is a solution which is:
Pretty
Returns a statically well-known type instead of the anonymous type (I tried to project the query result, but I got into problems with the OrderLines)
Runs Distinct on the server side
Anyone?
Even if the database tables do not have a foreign key relationship setup, you can configure Entity Framework as if they do.
Add an OrderDetails navigation property to your Order class and then just query Orders.

EF: One-to-many relationship - querying for a subset of the data

I am trying to fetch a collection of entities from a one-to-many relationship as an IQueryable so I can filter the data down before fetching this from the database.
To make it clear, consider the following example:
I currently have an entity "User" which has a collection of Pictures:
public virtual ICollection<Picture> Pictures{ get; set; }
The Picture entity may or may not belong to a User, and hence, doesnt have the User property in its definition.
A user may have thousands of pictures, but I would like to select the first 10 for example, ordered by Picture.Id. Is there a way to do this?
Maybe something along the lines like:
IQueryable<ICollection<Picture>> pictures = context.Users.Where(u=>u.UserId == userId).Select(c => c.Pictures)
Thanks!
The basic idea is to use the OrderBy and Take methods on the Pictures collection of the user. However, since you want to make sure that you only perform a single EntityFramework SQL query without loading the entire Pictures collection of a user, this needs to be expressed in a slightly more specific way.
Query syntax
var result = (from u in users
where u.Id == userId
from p in u.Pictures
orderby p.Id
select p).Take(10);
Method syntax
var result = context.Users
.Where(u => u.Id == 2)
.SelectMany(u => u.Pictures)
.OrderBy(p => p.Id)
.Take(10);
Note the call to SelectMany. It's important. Basically this adds up all the Pictures collections of all the selected users into one list and continues the query on this flattened meta-list. In theory this sounds like a pretty big operation, but in this case there should only be one user with a specific ID, so it really just continues with the selected user's Pictures collection. The generated SQL is a single, fast query:
Resulting SQL query (for both of the above)
SELECT TOP (10)
[Extent1].[User_Id] AS [User_Id],
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name]
FROM [dbo].[Pictures] AS [Extent1]
WHERE ([Extent1].[User_Id] IS NOT NULL) AND (2 = [Extent1].[User_Id])
ORDER BY [Extent1].[Id] ASC

JQgrid / Entity Framework Issue with entities that have a relationship

I have an entity that has a relationship with another entity. I am able to search on columns that are in the main entity, and include columns from the relationship entity. But I need to be able to filter the list (search) on columns that are not in the relationship entity.
for example
the Invoice Entity contains a customerId property, and is related to the Customer Entity which contains the customerName property
I need to be able to search / filter the grid by customerName.
I am new to entity framework, please help.
thanks
Carl
Your relation is 1->1. In these cases I usually return a custom class to the grid that has all the columns I need, including joins with other tables.
So basically what you need is to create a custom linq query with your resultset.
The mais query should follow this example:
var q = from i in ctx.Invoices
join c in ctx.Customers on i.CustomerID equals c.CustomerID
select new{InvoiceID=i.InvoiceID, InvoiceDate=i.Date, CustomerName=c.Name};
Now, assuming we receive a CustomerName variable with the string to filter by c.Name we could do:
if(!string.IsNullOrEmpty(CustomerName))
{
q = q.where(c => c.Name.ToLower().Contains(CustomerName.ToLower()));
}
Notice that I'm performing a ToLower() operation and a Contains, this will beahave as a LIKE ingnoring case sensitivity and searching for the string anywhere in the Customer Name.
At the end you'll return the q.ToList() serialized for the jqGrid...

return relationship data from database - xml, multi lines, other?

I have an web app which uses a DB for storage.
The code is C# there are two classes country and company.
The Company class contains a property with the relationship
List(Guid) CountryIds{get;private set}
The information is stored in the following manner in the db:
Company
Company_Country
Country
An example query is:
select c.* , cc.CountryId
from Company c
inner join Company_Country cc on c.id = cc.CompanyId
where (c.SomeColumn like 'somerestriction')
The question: What the most efficient way or even the current defacto standard to retrieve the relationship data from the database?
The options as I see it are:
use the above sql then in the c# code loop through the returned code adding the country id's to the correct company (very quick using a dictionary)
select the list of companies and then go back for each one with a separate sql query to get the list of country ids (simplest but big overhead to reconnect to the sql sever)
Use T-Sql to return the countryId in a xml format then use linq to extract the xml list from that comment (see sql below), note I would like to avoid delimited id strings.
Something like:
with cte(Id, CountryId) as
(
select CompanyId,
(SELECT CountryId as CountryId
from Company_Country p2
WHERE p2.CompanyId = p1.CompanyId
FOR XML PATH('')) AS CountryId
from Company_Country p1
group by CompanyId
)
select ss.*, cte.countryid
from StandardKitContent ss
inner join cte on cte.id = ss.id
order by ss.id
4 Other? (please comment)
Many thanks
Choco
If you're on a recent version of .NET, I recommend Entity Framework; it will slurp up your database tables, identify the relationships (if not automatically, then you can specify them in the designer or XML definition). Once that's done, it will generate business objects which will accurately reflect them, and you'll be able to do CRUD operations to your objects and have them persisted to your database.
Good luck!