I have a Database table like below,
ID Author Book
1 Kate Smuggler
2 Harper Smuggler
3 Slater Smuggler
4 Kate Katy
5 Smitha Katy
i want to retrieve all Book names(Distinct) based on the author name and display them on list view, i wrote the code below to Retrieve distinct values
int UserID = Convert.ToInt32(Session["User"]);
var Li = (from s in Data.TableName where s.Author == UserID select s.Book).Distinct().OrderBy(ID=>ID);
ListViewChatList.DataSourceID = "";
ListViewChatList.DataSource = Li;
ListViewChatList.DataBind();
but i get the following error 'System.String' does not contain a property with the name 'ID'.
How to solve this ?
This part:
select s.Book
is selecting just the book (title) part of the record. You can't get back from that to the ID... there can easily be multiple IDs for the same title, as per your sample data.
It's not clear what you'd want that query to return anyway, given that you're getting distinct book titles - ignoring the author, would you want IDs 1 and 4? 2 and 5? 3 and 5? Both represent the same set of distinct titles (Smuggler and Katy).
You could potentially group by name, and then do whatever you want with the IDs for the books with the shared name - but you really need to consider what your distinctness criterion means for the results.
Here's a query which will give you the lowest ID for each name:
var query = from s in Data.TableName
where s.Author == UserID
group s.ID by s.Book into g
select g.OrderBy(id => id).First();
It's not clear whether that's what you really need though.
var Li = from s in Data.TableName
where s.Author == User
orderby s.ID
select s.Book;
You're only selecting the Book column (a string), and then trying to order by ID, which you no longer have access to, and which certainly is not a property of the Book string.
Assume this is your data:
ID Author Book
1 Kate Smuggler
2 Kate Smuggler2
3 Kate Smuggler
4 Frey Katy
5 Smitha Katy
If you do the following, you'll get the first three books listed above:
(from s in Data.TableName where s.Author == "Kate" select s.Book);
Then you do a distinct, which reduces the books to the two unique ones (Smuggler and Smuggler2):
(...).Distinct();
Then you try to order by the ID, but you didn't originally select it so you don't have access to it. And you've taken a Distinct on the results, so you've lost some of the detail.
Since the two "Smuggler" books have been reduced to one, but their IDs were 1 and 3 (in my example), what should ordering them do? Should the single "Smuggler" book appear before "Smuggler2" or after?
Related
I have a rent a car project.
This is the table where I keep the rented vehicles
I want to find the most rented vehicle in this table. How can I do this?
So I want to find the most mentioned car Id in the table
[I have to do it with context architecture. How can I do this with c # linq?]2
I want to find the most rented vehicle in this table.
So basically you want to find out how many times car 5 is rented, and how many times car 6 is rented, etc, and keep the carId with the highest rental count.
As you are working with a database, my advice would be to use GroupBy to make groups of rentals that have the same CarId, and then keep the group that has the most number of rentals = order by descending count and take the first.
We'll use the overload of Queryable.GroupBy that has a parameter resultSelector, so we can select the number of rentals in the group as result.
// make groups of CarRentals that have the same CarId:
var mostRentedCarId = dbContext.CarRentals.GroupBy(carRental => carRental.CarId,
// parameter resultSelector: for every CarId and all CarRentals that have this CarId,
// make one new object
(carId, carRentalsWithThisCarId) => new
{
CarId = carId,
RentalCount = carRentalsWithThisCarId.Count(),
})
// order the groupBy result by descending rentalCount and take the first or default:
.OrderByDescending(groupByResult => groupByResult.RentalCount)
.FirstOrDefault();
if you mean that you want to find the sql query string for that question u can use the count() to count how many times the id of a specific car is repeated. And since you want the most rented car you can use somthing like this:select top 1 count(CarId) from tableName group by CarId order by count(CarId) desc
this should work for you.
You could write a query like the below, or use the approach as suggested by Abdelghafour Lahrache.
SELECT MAX(CarCount)
FROM
(
SELECT COUNT(CarId) AS CarCount
FROM YourTableName
GROUP BY CarId
) CarIdCounter
I've a Many to Many relation between a student (etudiant) and a course (cours) table which is called studentCours in SQL but not use as a model in Entity Framework (i've taken the habit of it now, even if i think its weird).
I need to show the result of the student (which is on another table etuResult) but the student may not have any result (nullable int) yet as the year is still in progress !
I'm able to get the value of studentCours and show them and also of studentResult, but i'm not able to show the concatenation of both (and leave the result empty or with other value than a number between 1 and 20).
On the following picture you can see :
On the left : the student with the id 3 has 2 cours with the id 1 and 10 (i dont know why the course_id 1 appears twice...) => These are the course he's following.
On the right : The student with the id 3 has one result for the course_id 10 and has the result 10/20
Here are my two queries to get the data :
var etuCours = from c in bdd.cours
where c.etudiant.Any(e => e.etudiant_id == id)
select new resultCours { cours_id = c.cours_id, libelle = c.libelle, code = c.code, annee = c.annee };
IEnumerable<resultCours> etuResult = from er in bdd.etuResult
where er.etudiant_id == id
select new resultCours { cours_id = er.cours_id, cote = er.cote };
I have two tables:
users:
ID Name
----------------
1 Bob
2 Dave
3 Mike
Books:
ID UserId BookName
------------------------
1 1 Cat in Hat
2 1 Happy Birthday
3 1 One Fish
4 2 Goldilocks
5 2 Three Crows
6 3 Hitchhikers
UserId is a key showing which books each user owns
In my html I want to create output that looks like this:
Name Books Owned
-------------------------
Bob Cat in Hat, Happy Birthday, One Fish
Dave Goldilocks, Three Crows
Mike Hitchhikers
Currently I am doing this with a loop and nested query:
var queryusers = db.Query("SELECT * FROM users");
foreach (var user in queryusers) {
<span>#user.name</span>
var querybooks = db.Query("SELECT * FROM books WHERE userid = #0", user.id);
foreach (book in querybooks ) {
<span>#book.bookname</span>
}
}
I know that's not good, but I don't know how to do this with JOIN. If I try:
var queryusersandbooks = db.Query("SELECT * FROM users INNER JOIN books ON users.id = books.userid");
My query returns 6 rows, but I only want 3. Is there a way to do this without having a SQL query in the loop?
Thanks
You are looking for GROUP_CONCAT. Try something like this:
SELECT name AS Name, GROUP_CONCAT(books.bookname SEPARATOR ', ') AS Books
FROM books INNER JOIN users ON users.id=books.userid
GROUP BY books.userid;
Keep in mind that GROUP-CONCAT has a 1024 character limit, so if you need more space, set a bigger threshold before executing the SQL, like this:
SET SESSION group_concat_max_len = 1000000;
SELECT name AS Name, GROUP_CONCAT(books.bookname SEPARATOR ', ') AS Books
FROM books INNER JOIN users ON users.id=books.userid
GROUP BY books.userid;
Here is a working fiddle.
Try something like this
SELECT u.name,CONCAT_WS(',',b.bookname) AS user_books FROM users u INNER JOIN books b ON u.id = b.userid GROUP BY u.id
If I were going to do something like this in mysql, I'd group by user and use group_concat to combine the results:
select users.id, users.name, group_concat(bookname) as books
from users inner join books on books.userid = user.id
group by users.id, users.name
You can order and specify the separator if you like, read about group_concat for more details. This breaks down quickly if there might be a lot of books, or if you want each book to be its own column or anything like that, but it's fine in simple cases.
You are on the right track. In your original code the inner foreach would have executed 6 times as well, once for each of the books.
Using the code below (basing off your own code), the query would still return 6 rows, as you have found, but only prints the user name once.
var queryusersandbooks = db.Query("SELECT * FROM users INNER JOIN books ON users.id = books.userid ORDER BY users.name");
int curruser = 0;
foreach (var userandbook in queryusersandbooks)
{
if (userandbook.userid != curruser)
{
<span>#userandbook.name</span>
curruser = userandbook.userid;
}
<span>#userandbook.bookname</span>
}
Why is my code not working as expected? The others (departmentName, employeeName and statusDescription) are working (shown below)
int countRow = 1;
//Query for account status
var query = from emp in db.EmployeeDetails
join stat in db.Status on emp.statusId equals stat.statusId
join dep in db.Department on emp.departmentId equals dep.departmentId
where emp.employeeName == name
select new { emp, stat, dep };
foreach (var q in query)
{
Console.WriteLine("{0,-3} | {1,-10} | {2,10}\t\t | {3,10}",
countRow,
q.dep.departmentName,
q.emp.employeeName,
q.stat.statusDescription);
Console.WriteLine("-----------");
countRow++;// <---------not adding: output keeps printing 1
}
It's working but my countRow is constantly having a value of 1
Right now, my output looks like this:
No. Dep Name Status
1 Finance John Present
1 Education Mary Present
1 Recreational Tom Absent
What I'm looking for is this:
No. Dep Name Status
1 Finance John Present
2 Education Mary Present
3 Recreational Tom Absent
UPDATE:
It appears my "query" (in foreach var q in query) has a count value of 1. I suppose this is the cause of my issue. Does anyone know how I can fix this?
It seems like you're posting the results of multiple queries.
Your original query looks for a specific name (emp.employeeName == name) which yields, probably, a single result. The results you posted have multiple names in them, which means you're running this query more than once (maybe in an enclosing loop?). Each query initializes countRow to 1, so you get the same number every time.
If you had multiple employees with the same name, you'd see numbers other than 1. As the comments suggest, try to find the enclosing loop and move the countRow = 1 initializer there.
Assume we have the following data in a SQL Server table (sorted by name) :
Id Name LName
-------------------------
5 Abbas Dayyan
3 Mohammad KD
4 Nima Ahmad
1 Omid Zangene
2 Pedram Ahmadi
we have an Id query string and we wanna get the next and previous row (if exists) from Id.
e.g :
the Id query string is 4, so we wanna get Mohammad KD as previous row and Omid Zangene as next row.
Could you please guide me how can do it with LINQ to Entity Framework.
Edit:
In practice the number of table rows is around 1 million.
Table rows didn't sort by Name by default, wa need to sort them by Name for the result.
How about this?
var result = (from person in db.People
where person.Id == id
let ordered = db.People.OrderBy(p => p.Name)
let reversed = db.People.OrderByDescending(p => p.Name)
let previous = reversed.SkipWhile(p => p.Id != id).Skip(1).FirstOrDefault()
let next = ordered.SkipWhile(p => p.Id != id).Skip(1).FirstOrDefault()
select new { previous, next }).First();
Edit: Took the new specifications into account.
Edit 2: Modified the code to not use LastOrDefault, which doesn't work with LINQ to Entities.
Try this:
int id = 4;
var list = (from x in ctx.Table
where x.id >= id - 1 && x.id <= id + 1
select x).OrderBy(o -> o.name).ToList();
edit: this will return elements with ID 3,4 and 5. I dont know if you are actually ordering the table in the database by name, but if you are i think it would be easier to just use a loop instead of using linq to get the previous and next element.
update: sorted the result by name