Sorry for my bad English. I have a problem. I want to create dynamic where clause in a LINQ query. I have one list object name "list1" having values Country, City, State and one datatable that has column named Name, Lastname, Country, City, State. I want to compare list1 values with datatable columns and get null / empty rows.
So I want a LINQ query like this:
var query = from p in datatable.AsEnumerable()
where list1 == null
select p
but it returns an error. How can I solve this problem?
Thanks in advance.
Ok, let's get going - your query is ridiculously bad.
You should not have datatable.AsEnumerable - that forces a table scan (running through the whole table).
Second, you have to code all fields expressively. This is going to get nasty - per definition Depending on size of list this will be very bad.
In general, every query is an IQueryable itself, so you can chain where conditions.VERY nice - I use that partially myself, defining the core query, then adding additional where clauses as needed (by input parameter) before executing.
Sadly, comparing a table against a list of elements by individual field match is as bad as it gets from the sql level.
Related
I have a Clients table which has the following columns:
Id, FirstName, LastName, CurrencyId, Gender.
I want to select the client's Currency that corresponded to Id 10 so I am doing something like this:
var currencyId = Db.Clients.FirstOrDefault(c=>c.Id == 10)?.CurrencyId;
Does this line bring all properties from Db and selects the currency in the code or it executes something like this in the database:
SELECT currencyId FROM Client WHERE ID = 10
Or I should write the linq like this:
var currencyId = Db.Clients.Where(c=>c.Id == 10).Select(c=>c.CurrnecyId).FirstOrDefault();
What's the difference between the two queries?
And what is the correct way to translate the above SQL query into a linq query?
Looked into it myself cause I found the anwser from most people questionable. I expect the FirstOrDefault to materialize the result (you also see from the type that you are not longer working with a query object), so that would mean it queries for all properties.
Unlike the 2nd query where you are still working with a query when filtering the property you like, thus dependent on the implementation it could be used for filtering properties and selecting specific fields.
The following is an example of the queries generated using EF for two similar queries, where it shows both generating different queries: https://dotnetfiddle.net/5aFJAZ
In your first example, var currencyId = Db.Clients.FirstOrDefault(c=>c.Id == 10)?.CurrencyId; the query selects the entire object to memory and then returns the Id property from that in memory object. As a result it needs to do something like the following SQL: SELECT * FROM Clients WHERE Id = 10. I understand I'm not using a parameter here and EF does spell out every column. However the key to understand here is that by returning more columns than you need, you potentially are setting up a performance concern because a covering index on Id and CurrencyId would not be used.
Your second LINQ query would use a SQL statement like SELECT CurrencyId FROM Clients Where Id = 10 which would take advantage of your indexes assuming you have an index covering these columns.
Sounds trivial but I cannot find an elegant answer to this: how do I read all rows of a specific column into a list of strings for instance using LINQ on Entity Framework context?
You could try something as simple as the following:
var rows = dbContext.TableName.Select(x=>x.ColumName);
where dbContext is the class you use to "talk" with your database, TableName is the name of the table, whose column values you want to read and ColumnName is the name of the column.
Furthermore, if you place a ToList after the Select, you will create list of objects whose type would be the type of the values in column called ColumnName.
Christos answer will just give you an IQueryable. If you want an actual List you need to do something with the IQueryable:
var rows = dbContext.TableName.Select(x=>x.ColumName).ToList();
though I might go for the LINQ syntax:
var rows = (from c in dbContext.TableName
select c.ColumnName).ToList();
The two forms are equivalent.
im calling a table with 200.000 rows and 6 columns, but i only want 2 of these columns to be used in one controller, so i want to know if there is a better way to call them from the server without compromising performance, because as i know Linq queries get the whole table and them makes the filtering, i think maybe Views is a good way, but i want to know if there are others and betters, Thanks.
for example:
var items = from i in db.Items select new {i.id,i.name};
in case i have 1.000.000 items, will it be a trouble for the server?
Your initial assumption is incorrect.
In general LINQ queries do not get the whole table. the query is converted into a "server side expression" (i.e. a SQL statement) and the statement is resolved on the server and only the requested data is returned.
Given the statement you provided you will return only two columns but you will get 1,000,000 objects in the result if you do not do any filtering. But that isn't a problem with LINQ, that's a problem with you not filtering. If you included a where clause you would only get the rows you requested.
var items = from i in db.Items
where i.Whatever == SomeValue
select new { i.id, i.name };
Your original query would be translated (roughly) into the following SQL:
SELECT id, name FROM Items
You didn't include a where clause so you're going to get everything.
With the version that included a where clause you'd get the following SQL generated:
SELECT id, name FROM Items WHERE Whatever = SomeValue
Only the rows that match the condition would be returned to your application and converted into objects.
I have an MSSQL database with LINQ to SQL.
I have three tables.
Requests -> id, string name
Results -> id, requestID, int jumps
Places -> id, resultID, int location
Then, using an input string, I need to get an ICollectable or array or something of Place which meets the following:
Each Request that has name=input, take its ID.[you can assume only one has]
Each Result that has requestID=ID[from above] - take its id.
Each Place that has resultID='id[from above]' - append to array for further processing.
I made it by looping on all Results and then executing another LINQ statement, but its extremely slow [about 500ms for a single request!]. Can I make it any faster?
Thank you!
Edit: Whoops, I also need it grouped by result. aka a List of List of Places, while each inner list contains one column from Result.
You can perform table joins in Linq2Sql using the join keyword:
var places = from request in Requests
join result in Results on request.Id equals result.requestID
join place in Places on result.Id equals place.ResultId
where request.name = input
select place;
Somthing like
Requests.Where(r => r.name == input).Results.Places.Select();
If this is too slow then I expect you need some indexes on your database.
If you don't have the relationships in your model then you need to establish some foreign key constraints on your tables an rebuild your model.
Using a SubSonic (2.2) SqlQuery object, I am querying a view that contains distinct rows from another table. The results of the query, however, contain multiple rows for certain rows in the view. It appears to be because of a join on a temporary table in the query generated to achieve paging. How can I avoid this duplication of rows?
Bonus points: I have to use the view because SubSonic can't do .Paged() and .Distinct() at the same time. Why not?
If I remember correctly you have to use distinct on the right position.
var query = DB.Select().From<Products>()
.Where(Products.CategoryColumn).IsEqualTo(5).Distinct();
var query = DB.Select().Distinct().From<Products>()
.Where(Products.CategoryColumn).IsEqualTo(5);
Both statements compile but the first generates invalid sql code. A good starting point for debugging SubSonic SqlQueries is to generate the output:
var sql = query.BuildSqlStatement();
Another solution could be to use Group instead of distinct so you can avoid the view in the first place.