How can we make Telerik Grid generate such kind of simpler queries? - telerik-grid

We use Telerik Grid (in ASP.NET AJAX).
It's convenient to use column grid filters because it let us avoid lot's routine job.
But the bad size is that it used to generate such kind of queries to our SQL Server:
SELECT *
FROM [dbo].[OPCatalogue] AS [t0]
WHERE (CONVERT(NVarChar(MAX), (CASE
WHEN 0 = 1 THEN CONVERT(NVarChar(40), '')
ELSE CONVERT(NVarChar(40), [t0].[SKU])
END))) LIKE 'something%'
This query works without using indices, so it would be much more prefer to construct the SQL like this:
SELECT *
FROM [dbo].[OPCatalogue] AS [t0]
WHERE [t0].SKU LIKE 'something%'
This way it's going to use the index and work much faster.
How can we make Telerik Grid generate such kind of simpler queries?
Thanks!

Related

Kentico - Multiple Choice Dual List Form Control

I found this Multiple Choice Dual List (with Sort) form control and have a question about the sorting functionality. From the description, it looks like the sorting functionality only works if we have something like this CHARINDEX(','+CONVERT(varchar, ItemID)+',', ',1,3,2,5,4,') in the Order By field. I tested with a couple of items and saw that if I hard-coded the Order By as instructed, it worked. Is there a way / something to put in the Order By so that it accepts the (new) order of the items in the second (red) box - without hard-coding? THANK YOU!
My authors (the left box) are from a SQL query.
The WHERE statement of my Repeater is like this, if it's of any help:
'|' + '{%CurrentDocument.Authors#%}' + '|' LIKE '%|' + CONVERT(varchar, AuthorsID) + '|%' Everything is working; I just need that sorting functionality to work dynamically.
I think the easies way to achieve this would be implementation of some logic on the client with javascript/jquery.
That would be my tool. The example order by is meant to show kind of how it works, your order by would look like:
CHARINDEX(','+CONVERT(varchar,AuthorsID)+',', '{%CurrentDocument.Authors#%}')
Assuming that Authors is the field that has the multiselect with order form tool, and AuthorsID is the table's identity row.
Does that help?

Designing library to generate dynamic MDX query

We are generating MDX query dynamically. We pass list of Columns ([DimesnionName].[Attribute.Name] format), Rows ([DimesnionName].[Attribute.Name] format) and Filter ([DimesnionName].[Attribute.Name].[Member Name] format) along with other inputs like, cube name, page number, measure etc.
This information is passed to a C# library and then we use lot of 'If' and 'Else' conditions to process this input and generate MDX query as a string. It requires lot of string manipulation.
You can say it has a workflow. After going through each condition, system generates some output. I am wondering if there is a smarter way to design this library.
I want to remove if else conditions.
I want to make it more readable.
I want to make it more manageable
My Question is: Is there any design principle I can use? I can think of using Windows WorkFlow. Please provide your suggestions
I'm actually on here to see if someone has done just that so I don't have to. No luck so far. But off the top of my head what you might want to look at is some form of rules engine that will evaluate the state of target string and add your various criteria.
Now I haven't even started to look into the syntax of MDX. I'm not that far along, but if I wanted to create an engine to create sql queries I'd look at the parts ( simplest case first ) you need list of columns, a table and list of where clauses. So you could have three or maybe just two basic engine classes one that takes a list of strings and (or better yet a list of expressions) and concatenates them ( or evaluates and then concats them ). If target string is empty then targetString = "select "+ x else targetString = ", " + x. Then do something similar with the where expression. You can get considerably more fancy for that building classes that implement the different forms of where expressions and so on. Then ultimately you'd pass your engine something like
MySqlEngine(new[] {"FirstName", "LastName", "GirlFriendsAddress"},
new []{EqualsExpression("FirstName","Brown"), EqualsExpression("LastName",Dynamite")},
"People");
and it would return
"SELECT FirstName, LastName, GirlFriendsAddress From People Where FirstName = \"Brown\" AND LastName = \"Dynamite\""
I would highly recommend using Expressions to evaluate properties on a target model that matches your table. Then you could make MySqlEnigine(...) you wouldn't have to provide to table name because your model could be named the same and you'd use no strings except for target value of the where clauses.
I know this is not the engine you want but I don't know MDX yet so you'll have to use this as an analogy.
Final thoughts DO NOT USE Window Workflow. You will want to kill yourself half way through and if you make it all the way through than there will be developers cursing your name for many years in the future.
Good luck
oh and if you build the please open source it and tell me so I don't have to do it.

Expression Engine - Is it possible for exp:channel:entries tag to have complex filters?

Coming from Codeigniter and new to Expression Engine, I am at a loss on how to do complex filters on the exp:channel:entries tag.
I am interested in this filters
status
start_on
stop_before
How do you do you implement filters for a complex condition like this?
(status=X|Y|Z AND start_on=A AND stop_before=B) OR (status=X AND start_on=C AND stop_before=D)
Is this even possible?
You can only use the search= parameter to search on “Text Input”, “Textarea”, and “Drop-down Lists” fields unfortunately. So you'd need to use the query module for this.
If you're just querying on those parameters you should be able to get the entry id's you need from the exp_channel_titles table, then use something like the Stash plugin to feed the entry_id's of the results into a regular channel entries tag. Yes it's nominally one more query that way but as EE abstracts the db schema fairly heavily the alternative is to get lost in a mess of JOINs.
So something like (pseudocode, won't work as is):
Get the entries, statuses are just a string in exp_channel_titles, entry_date is the date column you want - which is stored as a unix timestamp, so you'll need to select it with something like DATE( FROM_UNIXTIME(entry_date)) depending on the format of your filter data.
{exp:stash:set name="filtered_ids"}{exp:query sql="SELECT entry_id
FROM exp_channel_titles
WHERE status LIKE ...<your filter here>"
backspace="1"
}{entry_id}|{/exp:query}{/exp:stash:set}
Later in template:
{exp:channel:entries
entry_id="{exp:stash:get name="filtered_ids"}"
}
{!--loop --}
{/exp:channel:entries}
Yes it's a mess compared to what you're probably used to in pure CI, but the trade off is all the stuff you get for free from EE (CP, templating, member management etc).
Stash is awesome by the way - can be used to massively mitigate most EE performance issues/get around parse order issues
You can get a lot of this functionality using the search= parameter in your {exp:channel:entries...} loop.
It's not immediately clear to me how you'll get the complexity you seek, so you might end up resorting to the query module though.
If you're working with dates you might find the DT plugin useful.

Select a percentage of records using CRM 2011 Dynamic Entity

I'm developing service which consumes CRM 2011 data via dynamic entities (as in, Microsoft.Xrm.Sdk.Entity, the late-binding method). I'm deliberately not using Xrm.cs method (early binding) in an attempt to keep my solution generic.
Also, I want to avoid connecting to a CRM database directly (e.g. EDMX) as this would stop my solution being usable for a hosted CRM (e.g. with no direct DB access).
I have the following (simplified) requirement, I'm really struggling with the selection criteria:
A random 7% of records needs to be selected (and updated).
In SQL, the selection criteria would be relatively easy - I know how to select a random percentage of records. Something like:
SELECT TOP 7 PERCENT * FROM
(
SELECT TOP 1000 NEWID() AS Foo, [someColumns]
FROM [someTable]
)
AS Bar ORDER BY Bar.Foo ASC
This works perfectly. I gather the LINQ equivalent is something like:
from e in someEntities
orderby Guid.NewGuid()
select e;
There's a problem though, I don't know of a way to use LINQ with CRM 2011 dynamic entities - instead they insist on using either some restrictive QueryExpression classes/syntax, or fetchXML, as seen on this page (MSDN).
I've identified the following options for fulfilling this requirement:
Using dynamic entities, return the whole record set into a List, then simply choose a random selection by index. This however involves returning up to 10,000 records over an internet data service, which may be slow/insecure/etc.
Use a fetchXML statement. Unfortunately I don't know fetchXML, so I don't know if it's possible to do things like COUNT, TOP, PERCENT or NEWID().
Use Xrm.cs and LINQ, or use a Stored Procedure, or a SQL view. All of these options mean tying the solution down to either direct database connectivity and/or early binding, which is not desirable.
Say no to the customer.
Any advise would be greatly appreciated! Can fetchXML perform this query? Is there a better way to do this?
FetchXML does not support this, so you are down to either 1 or 3. And you are right, 3 would only work in the On Premise version, as you can't connect directly to SQL with the CRM Online product. However, that's the one I would go with unless you are absolutely sure the customer will be moving to CRM Online. If you must go with 1, you can at least limit the returned columns to only be the GUID of the record to decrease the payload size. Then when you select your random records, just go get their additional columns if needed (of course this could end up being slower due to "chattiness" depending on how many random records you are dealing with).
Dynamics CRM 2011, at this point, can't give you the degree of querying power that SQL and other LINQ providers can give, so I really believe you'll want to say no to the customer and move to the on-premise version if he/she wants that kind of flexibility.
With that said, a variant of method #1 is to, rather than fetch all rows at once and then choose your random set, fetch a random set from the entity one row at a time until you have the number of rows you want. The downside of this method is that instead of one call to the DB, there are many, which slows down the overall retrieve speed. A POC is below.
As for #2, I believe it's possible to handle all of your request, with some degree of success, using fetchXml. In fact, the only way to get aggregated data is by using fetchXml, and it also supports paging.
As for #3, native SQL is your best bet to get everything you want out of your data at this point, but that notwithstanding, while the LINQ provider is limited, it's a lot easier to transition SQL statements to LINQ than to fetchXML, and it does support late-binding/dynamic entities.
//create a list of random numbers
List<int> randomNumbers = new List<int>();
//declare a percentage of records you'd like to retrieve
double pctg = 0.07;
//use FetchXML to count the # of rows in the table
string fetchXml = #"<fetch aggregate='true'>
<entity name='salesorder'>
<attribute name='salesorderid' aggregate='count' alias='countIds' distinct='false' />
</entity>
</fetch>";
EntityCollection result = _service.RetrieveMultiple(new FetchExpression(fetchXml));
int rowCount = int.Parse(result.Entities[0].FormattedValues["countIds"].Replace(",", ""));
//initalize the random number list for paging
for (int i = 0; i < Math.Ceiling(pctg * rowCount); i++)
{
randomNumbers.Add((new Random(unchecked((int)(DateTime.Now.Ticks >> i)))).Next(rowCount - 1));
}
randomNumbers.Sort();
//page through the rows one at a time until you have the number of rows you want
using (OrganizationServiceContext osc = new OrganizationServiceContext(_service))
{
foreach (int r in randomNumbers)
{
foreach (var er in (from c in osc.CreateQuery("salesorder")
//not especially useful to use the orderby option as you can only order by entity attributes
//orderby c.GetAttributeValue<string>("name")
select new
{
name = c.GetAttributeValue<string>("name")
}).Skip(r).Take(1))
{
Console.WriteLine(er.name);
}
}
}

Programatic control using Telerik OpenAccess ORM and the RadGrid

Ok, between following documentation, posts and videos that use syntax and tools that are no longer used or available, I'm really lost as to how to go about even using Telerik's OpenAccess. So I thought I'd ask for some help and hopefully someone out there has done this before.
I want to simply bind my OpenAccess entities to a RadGrid, but I want to use TemplateColumn in my RadGrid (in editmode, I want to use other controls like datepickers, dropdowns, etc.) Therefore, like the old way of doing things, I want to fire off the RadGrid's ItemDataBound event, for example, find the controls and set the controls to the appropriate values.
Old way that we were used to (You know, like the old fashioned way of something like setting a RadTextBox to a value from the RadGrid's DataSource, which was a DataReader:):
string strID = e.Item.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["campaignID"].ToString();
RadTextBox rtxtTitle = (RadTextBox)e.Item.FindControl("rtxtTitle");
rtxtTitle.Text = DataBinder.Eval(e.Item.DataItem, "title").ToString();
Does anyone have sample out there of how to do this? I would assume that I would also need to know how to bind the RadGrid in the first place, so an example of that would also be helpful (NOT using the actual OpenAccessDataSource control - I want to bind it in the NeedDataSource event of the RadGrid).
Thanks in advance...
The sample I found on the Telerik web site for DataBinding an OpenAccess result to a DataGrid looks like this:
IObjectScope scope = ScopeFactory.GetScope(HttpContext.Current);
string query = String.Format("SELECT * FROM {0}Extent", viewName);
IQueryResult result = scope.GetOqlQuery(query).Execute();
RadGrid1.DataSource = result.ToList();
This looks to be using OQL, but you could also use LINQ. I would toss this question to the OpenAccess team on the forums. They can probably point you to better resources.

Resources