Is there a way to build a QueryExpression returning just a particular set of records?
I have the following Criteria Types:
First:
Returns the first n Records (i.e. select top)
Last:
Returns the last n records
Every:
Returns every n'th record
For the type "First" I can use
queryExpression.TopCount = number_of_records
But I have no Idea how I can achieve the other types of criteria. The issue is that there are quite big data volumes and if I need first to get all records and query the result for example with Linq to customize the resultset I will probably have a performance issue.
If I could build the QueryExpression just selecting exactly what I need the whole thing gets more efficient.
Does anybody have an idea on how to achieve this with a QueryExpression?
The system in question is Microsoft Dynamics CRM Online
For the "last N" you can reverse the sort and use TopCount again.
For the "every Nth" you might want to consider paging the Query Expression.
Say you're looking for every 10th record. What I might do would be to set my page size to 10 (query.PageInfo.Count).
To iterate through the pages as quickly as possible I'd make my "main" query return only the GUIDs. When I retrieve a new page of GUIDs, I'd grab the first GUID and get the columns I want for that record using a separate Retrieve call.
Last N Records: quite simple order by particular field as descinding and then top N that's it
Returns the last n records
// Instantiate QueryExpression QEaccount
var QEaccount = new QueryExpression("account");
QEaccount.TopCount = 5;
// Add columns to QEaccount.ColumnSet
QEaccount.ColumnSet.AddColumns("name", "ah_account_type", "accountid");
QEaccount.AddOrder("name", OrderType.Descending);
Every nth Record:
Do you have any particular criteria here, for example give me all accounts where country =Germany
if yes then you can user condition to return particular set of records as below
// Define Condition Values
var QEaccount_address1_country = "Germany";
// Instantiate QueryExpression QEaccount
var QEaccount = new QueryExpression("account");
// Add columns to QEaccount.ColumnSet
QEaccount.ColumnSet.AddColumns("name", "ah_account_type", "accountid", "address1_country");
// Define filter QEaccount.Criteria
QEaccount.Criteria.AddCondition("address1_country", ConditionOperator.Equal, QEaccount_address1_country);
Related
I found an interesting issue in Entity Framework. Check the code bellow. Here i am using Contains() to find all matching Id rows from Table Test1 but when i add same id multiple times it returns only 1 item not duplicating items but i want to get duplicate items too. How can i do this then?
var ids = new List<int>();
ids.Add(1);
ids.Add(1);
var foo = ctx.Test1.Include("Test2").Where(x => ids.Contains(x.Id)).ToList();
YOu can not. You really need to learn the basic of how SQL works and how query works because your question is a fundamental misunderstanding.
when i add same id multiple times it returns only 1 item not duplicating items
Because the table STILL contains only 1 item. if you add the same ID multiple times, why would you expect it to return the row multiple times?
The way it is evaluated is:
Take row
Check whether the ID matches any of the provided list.
Next row.
So, regardless how often you put the ID into the list of approved id's, it OBVIOUSLY will only return one row. You do not get duplicate items because you do not have duplicate items to start with.
Like so often when using anything Ef related, it also helps to intercept and look at the generated SQL and the generated query plan - this at least will make obviously clear that you can not get 2 id's. Contains will be an IN clause, containing the list of values. Like I said above, contains checks for rows, it will not magically duplicate them.
I would suggest making the duplication manually after query - though in 25 years I have never seen this requirement coming up, so I would strongly suggest you check whether what you try to do makes any logical sense from a higher perspective first.
Why should it be the other way? Your EF Contains instruction has in SQL "IN" form:
SELECT
...
FROM ...
WHERE ... IN (1, 1)
I am trying to select a result set in to a list of object type.
var temp = res.Select(a => new ContentAudit {
locale = a.locale,
product_code = a.product_code, product_name = a.product_name,
image = a.image, product_short_description = a.product_short_description,
product_long_description = a.product_long_description,
items = a.items,
service_articles = GetServiceArticleCount(a.product_id).ToString(),
is_deleted = a.is_deleted, views = a.views,
placed_in_cart = GetPlacedInCartCount(a.product_id).ToString(),
ordered = GetOrderedCount(a.product_id).ToString(),
Importance = GetImportance(a.product_id),
operation = (a.product_id.ToString()) }
).ToList();
I am selecting from 'res' variable which is the result set selected from the database. Which has aroun 65000 records. So because of that the line of code above dosent work and the server get stucked. Is there anyother way i can achieve this? Thank you
There are many problems with this query.
1st You are trying to select 65000 records from DB and use .ToList()
It will iterate all objects.
You should use IEnumerable (or IQueryable), and use lazy loading.
If you do not need all of this objects try to add .Where() statement to limit number of entities.
2nd in query You are using methods wich are trying to make even more request to db. Do You realy need all this data? If yes make sure that everything is using lazy loading. Do not iterate it all in one time!
I can see two solutions. If You don't need all this data, take only data You need from db and limit number of retrived entitiies as much as its posible.
If you realy need all this data, try to use lazy loading, and add pagination (.take() and .skip() methods) to limit number of entites retrived in one call.
I want to get items 50-100 back from a result set in linq. How do I do that?
Situation:
I get back an index of the last item of the last result set. I want to then grab the next 50. I do not have the ID of the last result only its index number.
You order it by Something, else you really can't
So it would be Something like
mycontext.mytable
.OrderBy(item=>.item.PropertyYouWantToOrderBy)
.Skip(HowManyYouWantToSkip)
.Take(50);
LINQ is based on the concept of one-way enumeration, so queries all start at the beginning. To implement paging you'll have to use the Skip and Take extensions to isolate the items you're interested in:
int pageSize = 50;
// 0-based page number
int pageNum = 2;
var pageContent = myCollection.Skip(pageSize * pageNum).Take(pageSize);
Of course this just sets up an IEnumerable<T> that, when enumerated, will step through myCollection 100 times, then start returning data for 50 steps before closing.
Which is fine if you're working on something that can be enumerated multiple times, but not if you're working with a source that will only enumerate once. But then you can't realistically implement paging on that sort of enumeration anyway, you need an intermediate storage for at least that portion of it that you've already consumed.
In LINQ to SQL this will result in a query that attempts to select only the 50 records you've asked for, which from memory is going to be based taking numSkip + numTake records, reversing the sort order, taking numTake records and reversing again. Depending on the sort order you've set up and the size of the numbers involved this could be a much more expensive operation than simply pulling a bunch of data back and filtering it in memory.
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.
Say I have an IQueryable that will return a datatype with an ID property (column).
I want to further filter my query (I don't want to evaluate the query) as follows:
For each unique ID from the main query, I want to Take(n), where n is some arbitrary number.
That is, I want to only keep the first n rows for each unique ID.
I can get the distinct ID's...
var ids = query.Select(q => q.ID).Distinct();
and I can Take(n) with the rest of them, but I'm stumped on connecting the two:
query = query.<FOR EACH DISTINCT ID>.Take(n);
The accepted answer works, but is slow for a large table. I wrote this question as a follow-up.
You can do it like this:
query = query.GroupBy(q => q.ID).SelectMany(g => g.Take(n));
The GroupBy brings together the records with identical IDs, letting you process them as a group; SelectMany takes each group, limits the number of its members to n, and puts the results back into one flat list.