Get a child count using Bookshelf - bookshelf.js

I want to have child count for every record in table A. How do I query if I have sql statement like this
SELECT A.*, (SELECT COUNT(*) FROM B WHERE B.a_id = A.id) AS TOT FROM A

You may be able to achieve this using knex QueryBuilder
A
.query(qb => {
qb.select('(SELECT count(*) FROM B WHERE B.id = A.id) AS count');
})
.fetchAll()
.then(data => {
// Data retrieval
})
.catch(err => {
// Error management
})

Related

Simple condition with ProjectTo doesn't work

I have the problem with ProjectTo.
I have that Select map:
var posts = await appContext.Posts
.Select(x => new PostListReadModel()
{
IsAnonymous = x.IsAnonymous,
Publisher = !x.IsAnonymous ?
new PostPublisherReadModel()
{
Id = x.PublisherId,
Nick = x.Publisher.Nick,
PhoneNumber = x.Publisher.PhoneNumber,
Avatar = x.Publisher.Avatar
} :
null
})
.ToListAsync();
As you can see, I have a mapping condition for the Publisher property. Very simple condition.
It translates to sql like this:
SELECT p.IsAnonymous, NOT (p.IsAnonymous), p.PublisherId, u.Nick, u.PhoneNumber, i.Id, i.DateCreated, i.DateUpdated, i.FileName
FROM posts AS p
INNER JOIN users AS u ON p.PublisherId = u.Id
LEFT JOIN images AS i ON u.AvatarId = i.Id
And it works.
Now, I want to use ProjectTo. And I have a map configuration like this:
CreateMap<User, PostPublisherReadModel>();
CreateMap<Post, PostListReadModel>()
.ForMember(dest => dest.IsAnonymous, opt => opt.MapFrom(src => src.IsAnonymous))
.ForMember(dest => dest.Publisher, opt => opt.Condition(src => !src.IsAnonymous))
.ForAllOtherMembers(opt => opt.Ignore());
It translates to sql like this:
SELECT p.IsAnonymous, FALSE, i.Id, i.DateCreated, i.DateUpdated, i.FileName, u.Id, u.Nick, u.PhoneNumber
FROM posts AS p
INNER JOIN users AS u ON p.PublisherId = u.Id
LEFT JOIN images AS i ON u.AvatarId = i.Id
and it naturally doesn't work.
Is it an automapper error or am i doing something wrong?
P.S.: DbProvider: Pomelo.EntityFrameworkCore.MySql Version=3.1.0

How to convert sql limit query to linq lambda?

Here's an example that I want to convert to lambda query:
SELECT TOP(5) Pbschedules.s_id, Pbschedules.date, Pbworth2.worth, Pbschedules.pb_id
FROM Pbschedules INNER JOIN Pbworth2 ON Pbschedules.pb_id = Pbworth2.pb_id
ORDER BY s_id desc
var query = database.Pbschedules// your starting point - table in the "from" statement
.Join(database.Pbworth2, // the source table of the inner join
pbs=> pbs.pb_id, // Select the primary key (the first part of the "on" clause in an sql "join" statement)
worth=> worth.pb_id, // Select the foreign key (the second part of the "on" clause)
(pbs, worth) => new { PbsID = pbs.s_id, Worth = worth.worth /*other columns*/ }) // selection
.OrderByDescending(x => x.s_id)
.Take(5);
var myData = (from valuesPbs in Pbschedules join valuesPbw in Pbworth2
on valuesPbs.pb_id equals valuesPbw.pb_id
orderby valuesPbs.s_id descending
select valuesPbs
).Take(5);

Is there a way to select a columns from a joined table without explicitly listing all columns?

I'm trying to use JoinSqlBuilder to select a data from one of the joined tables, and can't find a way to do that unless I list all columns from that table. Hopefully I'm missing something and it actually can be done.
This is approximately what I have:
var sql = new JoinSqlBuilder<Product, Product>()
.Join<Product, Customer>(src => src.Id, dst => dst.Id)
.Where<Customer>(x => x.Id == Id);
and I want to select everything from a product table. The query above throws an exception complaining about column name collisions, so its clearly does a select from both tables.
Edit: In the end I want to have this sql (never mind the design, its not a real thing):
select
p.* //<-- This is the piece that I'm struggling with
from product p inner join customer c on p.id on c.productId
where blah;
Looks like OrmLite want me to explicitly list all columns I want to return, which I want to avoid.
Note: I'm using 3.9.71 of servicestack. I've not looked at the 4.0 implementation yet.
I think you have a FK relationship problem with your join. Assuming that a product has a customer FK named (CustID), it'd look like this. Additionally, you'd need a POCO to represent the result set, if you are returning a "combination" of the results. I don't think you'll want to return both "ID" columns, and instead return a FK column.
return _factory.Run<ProductCustomer>(conn=>
{
var jn = new JoinSqlBuilder<Product, Customer>();
jn = jn.Join<Product, Customer>(srcProd => srcProd.CustId,
dstCust => dstCust.Id, // set up join Customer.id -> Product.CustId
p => new { p.Id, p.OtherField}, // product table fields returned
c => new { c.Name, c.AddressId}, // customer fields returned
null, //where clause on the product table
cust=>cust.Id = customerId // where clause on the customer table
);
var sql = jn.ToSQL();
return conn.FirstOrDefault<ProductCustomer>(sql);
}
Hope this helps.
Edit: After your Edit, try this:
// set up join Customer.id -> c.ProductId
jn = jn.Join<Product, Customer>(srcProd => srcProd.Id, dstCust => dstCust.productId)
.Where<Customer>(c=>c.Id == custIdParameter);
var sql = jn.ToSql();
You can add a ".Where" again for the
Where<Product>(p=>p.id == foo);
if you need to add more product with your BLAH. This should get you close.
Have you tried the SelectAll extension method?
var sql = new JoinSqlBuilder<Product, Product>()
.Join<Product, Customer>(src => src.Id, dst => dst.Id)
.SelectAll<Product>()
.Where<Customer>(x => x.Id == Id);

How to sort in linq to sql for a joined table?

i have these tables in short:
Table: RPG
Coloumns: RPGID, Name
Table: RPGCharacter
Coloumns: CharID, RPGID, Name
Table: RPGPosts
Coloumns: PostID, CharID, Text, timestamp
So in Database the relation is:
1 RPG has X Characters and 1 Character has X Posts.
I get the information with this code:
public static List<RPG> GetAllRPGs()
{
using (RPGDataContext dc = new RPGDataContext())
{
return (from a in dc.RPGs where !a.IsHided && !a.IsDeleted select a).ToList();
}
}
The Problem is:
How to sort these list by the LAST post (TIMESTAMP-Coloumn of the RPGPOst-Table)?
Assuming you've got appropriate navigation properties set up, something like this should work:
var results =
(from a in dc.RPGs
where !a.IsHided && !a.IsDeleted
orderby a.Characters.SelectMany(c => c.Posts).Select(p => p.Timestamp).Max()
select a)
.ToList();
Or possibly:
var results =
(from a in dc.RPGs
where !a.IsHided && !a.IsDeleted
orderby a.Characters
.SelectMany(c => c.Posts)
.OrderByDescending(p => p.Timestamp)
.Select(p => p.Timestamp)
.FirstOrDefault()
select a)
.ToList();

LINQ - EF join difficulty

I have two tables:
Phase :
long ID
string Name
and another Activity :
long ID
string Name
long PhaseID
I already know the name of the phases and I want to get the activity for those particular phases. Do i add PhaseName to the activity table or do I do it through join in LINQ?
Maybe something like this?
var query = from a in entities.Activities
join p in entities.Phases on a.PhaseId equals p.Id
where p.Name == "Preplanning"
... and here im not sure how to finish this query..
Thanks for your help!
The code that you've provided will use an Inner Join to find all Activities where the Phase with Name "Preplanning" exists.
To finish your query you need to add a select clause.
var query = from a in entities.Activities
join p in entities.Phases on a.PhaseId equals p.Id
where p.Name == "Preplanning"
select a.Name
will return IEnumerable<string> of all activity names.
Just select activity, as you want:
var query = from a in entities.Activities
join p in entities.Phases on a.PhaseId equals p.Id
where p.Name == "Preplanning"
select a;
Here is how query expression should look like:
A query expression must begin with a from clause and must end with a select or group clause. Between the first from clause and the last select or group clause, it can contain one or more of these optional clauses: where, orderby, join, let and even additional from clauses. You can also use the into keyword to enable the result of a join or group clause to serve as the source for additional query clauses in the same query expression.
Same as puzzling image:
With method syntax you don't need to end query with something special:
var query = entities.Phases
.Where(p => p.Name == "Preplanning")
.Join(entities.Activities, p => p.Id, a => a.PhaseId, (p,a) => a);
No need to do a join if you only need data from one of the tables. You can apply a filter instead:
var q = entities.Activities.Where(a =>
entities.Phases.Any(p => a.PhaseId == p.Id && p.Name == "Preplanning"));

Resources