How to sort in linq to sql for a joined table? - asp.net

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

Related

How to get multiple column value from database into a list using LINQ query

I would like to get FullName, Emailcolumn values using LINQ query in c# to a list and then get these values, but it giving below error;
Cannot implicity convert type Systems.Collections.Generic.List<<anoynymous type: string FullName>>
List <PlayerDetails> details = (from x in conn.Table<PlayerDetails>().Where(x => x.Email == emailTextVal).Select(p => new { p.FullName }) select x).ToList();
SoccerAvailability soccerAvailability = new SoccerAvailability();
soccerAvailability.FullName = details[0].FullName;
soccerAvailability.Email = emailTextVal;
why don't you just select the entire PlayerDetail record?
List <PlayerDetails> details = conn.Table<PlayerDetails>().Where(x => x.Email == emailTextVal).ToList();
SoccerAvailability soccerAvailability = new SoccerAvailability();
soccerAvailability.FullName = details[0].FullName;
soccerAvailability.Email = emailTextVal;
alternately, you really only need to select the FullName, since you already know the e-mail value
You should not mix up Lambda with C# Expression, i mean you can, but i wouldn't recommend it.
I think this is the query you need:
(from x in conn.Table<PlayerDetails>()
where x.Email == emailTextVal
select new {
Name = x.FullName,
Email = x.Email
}).ToList()

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

LINQ Query in DataTable

I have a DataTable named dt. It has two Columns named atype_code and module.
Now i need to query a module based on specific atype_code.
Here is the code i wrote but not working.
DataTable dt = GetATypeCodeList();
var accType = (from myAccType in dt.AsEnumerable()
where myAccType.Field<string>("atype_code") == aTypeCode.Trim()
select myAccType.Field<string>("module"));
acctype is a System.Data.EnumerableRowCollection<System.String>.
Since you've said that you
need to query a module based on specific atype_code
, i assume that you want only one module with the given atype_code.
Then you should either use Single/SingleOrDefault or First/FirstOrDefault.
String firstModule = dt.AsEnumerable()
.Where(r => r.Field<string>("atype_code") == aTypeCode.Trim())
.Select(r => r.Field<string>("module"))
.FirstOrDefault();
// or
String singleModule = dt.AsEnumerable()
.Where(r => r.Field<string>("atype_code") == aTypeCode.Trim())
.Select(r => r.Field<string>("module"))
.SingleOrDefault();
Enumerable.Single throws an exception if there is more than one matching element. That can be useful to validate the data.
Edit:
Here's the query-syntax:
IEnumerable<String> modules =
from myAccType in dt.AsEnumerable()
where myAccType.Field<string>("atype_code") == aTypeCode.Trim()
select myAccType.Field<string>("module");
String module = modules.FirstOrDefault(); // returns null if no matching modules were found

linq to object get element from list

List<PrpSubjects> objListSubjects = _objSubjectDal.GetAllSubjects();
ddlSubjects.DataSource = objListSubjects;
ddlSubjects.DataBind();
_subjectName = objListSubjects...?
In _subjectName I want to fetch the subjectname from objListSubjects on basis of subjectid.
The subject list has subjectid and subjectname columns.
the question is i have a list with 2 columns subjectid,subjectname... the method returns a list of subject now i want to fetch the subjectname by subjectid,,, i thght instead of querying the database again i thght to use linq on list to fetch the subject name.. i hope i am clear about my requirement
_subjectName = objListSubjects
.Where(s => s.SubjectId == someId)
.Select(s => s.SubjectName)
.FirstOrDefault();
(will return null if there is no subject with the id someId)
_subjectName = objListSubjects.First(s => s.SubjectID == theIdYouAlreadyHave).SubjectName;
If you suspect that subject might not exist, you can use
objListSubjects.FirstOrDefault(s => s.SubjectID == id);
That will return null if it doesn't exist.
Or, if you find the sql style better to read ;)
_subjectName = (from s in objListSubjects
where s.SubjectId == someId
select s.SubjectName).FirstOrDefault();

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