linq-to-entities join 3 tables and group-by statement - linq

Consider the database schema in the picture.
I need a linq-to-entities statement that will retrieve authors and their respective books grouped by author. For example, I want to display something as follows:
authorName8
bookTitle27
bookTitle35
bookTitle62
authorName37
bookTitle9
bookTitle51
An additional constraint is the oject of grouped items has to be returnable by a method.
Can anybody formulate join and group-by statement (a) ordered by author name, (b) ordered by author name and book title?

You didn't mention which version of EF you are using, or whether you need to filter the authors by some condition, or filter the books by some condition. A general query that will fetch everything will look like this:
List<Author> authorsWithBooks =
context.
Authors.
Include(a => a.Books). // For EF 4.1
/*Include("Books"). instead for previous versions of EF */
/*Where(a => !a.IsDeleted). if you want to filter the authors */
ToList();
If you want to filter the book collections, you will have to write a more elaborate query though.

var query = (from customer in MyDataContext.Aurthor select author)
.Including(author=> author.Books);
This will get you all the authors and eager load the books for best performance.

Related

Runtime join in lightswitch

I have a generic group members table with a GUID for a "group type" and a GUID for "referenced object". An example would be if I have a table of customers(each having a GUID) I can group them under "already paid" by creating a group GUID and in my "Group members table" referencing every customer by their respective GUID. This allows for any type of group to be added to the model as we expand(without adding extra tables).
Here is the problem. I have created a subquery in an entity in order to filter the universal group members table for a certain group and what "items" are and are not in that group; like so:
partial void ElementsNotMemberOfGroup_PreprocessQuery(int? UniversalGroupTypeIDParameter, int? UniversalGroupsIDParameter, ref IQueryable<UniversalGroupMember> query)
{
query = query.Where(x => x.UniversalGroup.UniversalGroupType.UniversalGroupTypeID == UniversalGroupTypeIDParameter);
query = query.Where(x => x.UniversalGroup.UniversalGroupsID != UniversalGroupsIDParameter);
}
This returns the GUIDs for the referenced object in the group, but for a user that's useless. I need to join this table and my customers table at runtime on the GUID so I can extract the customer info and display it.
Any Ideas?
LightSwitch wasn't really created with this kind of scenario in mind. LightSwitch makes things very easy for you when you create relationships between tables that are, well, "related". When you do this, you never need manual joins between entities.
While it's possible to do something similar to what you're describing (see the link below), it's a lot more work to achieve it, and in my opinion it isn't really worth the extra trouble. Not only that, but as you're discovering, it complicates even the most simple operations.
In essence, you're working against LightSwitch, instead of with it. My advice to you would be that if you really must do this type of manual optimization, then LightSwitch may not be the best product for you to use.
Beth Massi has a blog article, Using Different Edit Screens Based on Record Types (Table Inheritance), which isn't exactly what you're doing, but it may give you some ideas if you decide to still use LightSwitch for your project.

code igniter datamapper join get()

I am using this join in my code igniter model
$this->db->select('e.name, p.projects');
$this->db->from('example as e');
$this->db->join('procure as p', e.id = p.id');
$this->db->where('e.cityid', '1');
$this->db->where('e.status', '0');
I do not have separate table for join. Here is my data mapper, this is not giving any output.
I have two tables and I want to write a join query on them.I have this in my controller.
$example = new Example();
$example ->where_join_field('procure', FALSE);
Update
can you show me the snippet for joining three tables using data mapper.
Generally you don't do joins by hand with DMZ models (the sql generated will use joins nonetheless). The thing you are looking for is Relations.
You have to set up your model's relations, using the $has_one and $has_many attributes, keeping the naming conventions, creating the necessary tables for many-to-many and so on. You can read about these in the docs here and here.
Once you got your models set up, you can use the where_related and include_related methods where you have used joins before:
where_related is for when you want to filter the models you are querying on some related model's field values. So if you have a related project set up on your Example class, you can write ->where_related('project', 'procure', false); and it will filter the returned Example instances based on their related project's procedure field. So basically it's the same conditionals that you would put into the where SQL clause.
include_related is for when you want to include fields from related models or even whole instance. So if you write ->include_related('project', 'projects') when you query Example instances you will end up with a project_projects attribute on the returned instances. There are many options to control how these attributes should be created. Basically these are the fields you would have put into the select SQL clause.
There are magic methods created for every named relation and many other options, i refer you to the Get (Advanced) page of the documentation for start and free to explore the other pages describing relations.

LINQ to CRM - OR in Where clause

I am trying to bring some data from Dynamics CRM 2011 using LINQ. The goal is to bring all Contact records that have changes since certain date OR have a child entity (PERC files) changed since that same date. The query looks like that:
// Bring all students who have changes (at Contact entity) after specific date
// momentInTime or the status of any of their perc files has been changed since
// that date
var students = (from c in ContactSet
join pl in cga_portallogonSet on c.Id equals pl.cga_ContactId.Id
join ef in cga_percfileSet on c.Id equals ef.cga_StudentId.Id
where
(pl.cga_PortalLogonRole.Value == 284970000) // student
where
(c.ModifiedOn >= momentInTime || c.CreatedOn > momentInTime)
||
(ef.cga_statuschangedate >= momentInTime)
select c.cga_StudentNumber).Distinct().ToList();
This produces the following error message:
'Contact' entity doesn't contain attribute with Name = 'cga_statuschangedate'.
I cannot figure out how to do OR on two different entities. The MSDN says you need WHERE clause for each entity:
where Clause
In order to filter the result set, where clauses can be added against one or more of the >entities. Each where clause may only contain conditions against an individual entity type. >A composite condition involving multiple entities is not valid. Instead, each entity >should be filtered in separate where clauses.
http://msdn.microsoft.com/en-us/library/ff681565.aspx
Is there another way of achieving what I need?
Unfortunately you cannot achieve what you want in a single linq statement beacuse the liunq provider they use boils down to fetchXML, and fetchXML does not support the scenario you are using.
More detail... Fetch gives you condition's inside of entity's or link-entity's. These condition elements cannot have attributes in them from other linked entities, only the direct parent entity or link-entity. Here is one of many microsoft forum posts referencing this limitation of fetchXML
Probably not the answer you were looking for, eh? As an ugly alternative you you can run two separate queries and filter in memory (as damaging as that may be to performance). Or better yet if you are an on-premise deployment you can write some sql against the filtered views. Good luck.

Use LINQ for double-nested OData collection

I've got a custom OData feed that for books. Each book can have multiple authors and an author can be involved in multiple books so I implemented this using a join table (Book - BookAuthorJoin - Author). My proxy object has Book.BookAuthorJoins BookAuthorJoin.Books & BookAuthorJoin.Authors.
What I want todo is have a single query where I get all the books for an author in a single LINQ query, but having trouble applying the filter. Seems I want two Expand() methods, but that isn't working. The following query doesn't work, but shows what I'm trying to do:
var query = from book in ODataContext.Books.Expand("BookAuthorJoins").Expand("Authors")
where book.BookAuthorJoins.Author.AuthorID = authorID
select book;
On the server side, the 1-to-many or many-to-many relationship is usually exposed as just a navigation property, exposing the join table in the middle will make your life much harder. If you use EF you should be able to hide the table and just expose the relationship as a navigation property.
In any case, to get all books for a certain author the query should look like:
/Authors(123)/Books
The result of this query is just a feed of books.
If you do keep the join table exposed then something like this migth work:
/Authors(123)/BookAuthorJoins?$expand=Book
But this time you get all the BookAuthorJoins with the Book for each as well.

Can someone explain Query Reshaping in Linq with the following example?

I am reading this asp.net article on building your first asp.net mvc 2 website and I came across a Linq query that uses the Include method in the query. I have used some linq, but I have never used the Include method and would like a better explanation. Does it translate to an join in linq? What is the benefit? Here is the query from the article:
var genreModel = storeDB.Genres
.Include("Albums")
.Single(g => g.Name == genre);
The article states that:
Entity Framework feature that allows us to specify other related entities we want loaded as well, called Query Result Shaping. We want to load the Albums for the matching Genre, so we'll query from Genres.Include("Albums") to indicate that we want related albums as well. This is more efficient, since it will retrieve both our Genre and Album data in a single database request.
I sort of understand what the author is saying above, but feel I would need a better example or explanation, especially since I have never used the Include method before.
If you inspect the generated sql, you'll notice that the Albums table is joined in. It should look something like:
SELECT [t0].*, [t1].*
FROM Genres [t0]
LEFT JOIN Albums [t1] ON [t0].GenreId = [t1].GenreId
WHERE [t0].Name == #p0
When the results get back to the client side, the ObjectContext will turn the row-column shape into instances of Genres and Albums. These instances will be related hierarchically - the single Genre with all of its Albums.
Suppose this genre has 5 albums. The query will return 5 rows. The object context will create one instance of Genre (each of the 5 rows has the same Genre primary key value).

Resources