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

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);

Related

Select data from multiple table with Entity Framework

I am able to select data from two tables, But I am getting partial result only while retrieving data from three tables.
var items = from orders in nobleappDbContext.JobOrders.Where(m => m.OrderStat == 0)
join users in nobleappDbContext.users on orders.Uid equals users.Uid
join customers in nobleappDbContext.customers on users.Uid equals customers.Uid into customdata
from m in customdata.DefaultIfEmpty()
select new
{
Eid = orders.Eid,
Uid = orders.Uid,
OrderStat = orders.OrderStat,
Name = m.Name,
Contact = (m.Contact == null) ? 0 : m.Contact
};
return Ok(items);
With this code, I am getting only result (common result) from users table and I am looking for something like UNION or OUTER JOIN.
Any help will be highly appreciated
finally I got exactly what I was looking for, here by posting the answer as I might help someone looking for same. LEFT JOIN with Entity Framework is the key
var query = from a in authurs
join b in books on a.Id equals b.AuthorId into auth_books
from left in auth_books.DefaultIfEmpty()
join bs in booksSeries on left.BookSeriesId equals bs.Id into books_bookseries
from left2 in books_bookseries.DefaultIfEmpty()
select new
{
Author = a.Name,
Book = left.Name,
BookSeries = left2.Description
};
var resList2 = query.ToList();
refer this link for further clarification.

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);

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"));

ASP.NET: Linq2SQL: selecting all names matching an id

Got 2 tables: db.Tags (ID, TagName) and db.Names (ID, Name, TagID).
I want to fetch all db.Tags rows, and all the Names matching the TagID.
So it will look like
ID - TagName - Names
1 - tag1 - name1, name2, name3
2 - tag2 - name4, name5, name6
Is this possible in one (long) linq query?
or do I have to get all the tags, then do foreach tag, get all the names, then do foreach names to put them in a one long string..
Thanks in advance!
EDIT:
Okay see my comment on the second answer (first one up..), this is what i tried but i get some errors in compiler:
var tags =
from t in db.Tags
orderby t.Priority ascending
select new {
t.ID,
t.Name,
t.Priority,
Places = String.Join(", ",
(from p in db.Places
join o in db.TagToPlaces on new {
p.ID,
t.ID
}
equals new {
o.PlaceId,
o.TagId
}
select p.Name
).ToArray()
)
}
);
I think this is what you're after:
var query =
from t in db.Tags
select new
{
t.ID,
t.TagName,
Names = String.Join(", ",
(from n in db.Names
where n.TagID == t.ID
select n.Name)
.ToArray()),
};
With this I get the same sort of output that you gave in your question. I also understood that you want to output the tag id and name even when there are no associated name records - my query does that.
Now depending on if you're using EF or LINQ-to-SQL or something else you may need to add .ToArray() to the db.Tags & db.Names references to force the database query to occur.
If you have a large number of tag records you'll find you have a large number of queries going to the database. You could make this change to reduce it to only two queries:
var tags = db.Tags.ToArray();
var names = db.Names.ToArray();
var query =
from t in tags
select new
{
t.ID,
t.TagName,
Names = String.Join(", ",
(from n in names
where n.TagID == t.ID
select n.Name)
.ToArray()),
};
Now you just need to make sure that your data fits into memory - but it sounds like it should. I hope this helps.
Since the concat is a pain in TSQL, I would query the 3 values "as is", and format from there:
var list = (from tag in db.Tags
join name in db.Names
on tag.ID equals name.TagId
orderby tag.ID
select new { tag.ID, tag.TagName, name.Name }).ToList();
for example, if I wanted the names by tag-id, I could do:
var namesByTag = list.ToLookup(row => row.ID, row => row.Name);
(or whatever else you choose)

Resources