I am creating a custom module in Orchard , I would like to create a query programmatically.
string queryName= "Product";
var item = _orchardServices.ContentManager.New("Query");
item.As<TitlePart>().Title =queryName;
_orchardServices.ContentManager.Create(item, VersionOptions.Draft);
if (!item.Has<IPublishingControlAspect>() && !item.TypeDefinition.Settings.GetModel<ContentTypeSettings>().Draftable)
_orchardServices.ContentManager.Publish(item);
var queryPart = item.As<QueryPart>();
queryPart.ContentItem.ContentType = queryName;
string desc =" filter for the query";
string contentType = "CommonPart.ChannelID.";
var filterGroupRecord = new FilterGroupRecord();
var filterRecord = new FilterRecord()
{
Category = "CommonPartContentFields",
Type = contentType,
Position = 0,
};
filterRecord.State = "<Form><Description>" + desc + "</Description><Operator>Equals</Operator><Value>ChannelId</Value></Form>";
filterGroupRecord.Filters.Add(filterRecord);
queryPart.FilterGroups.Insert(0, filterGroupRecord);
the problem is that:I want set a filters of the query,not a filters group.
could you tell me how to improve my code?
Database structure and class declarations make it impossible. Why do you need it?
Update:
I means that you must use FilterGroupRecord at least one.
But when Query published that Filter Group will be created automatically if query have not yet Filter Group (see at QueryPartHandler). You should add your filters to this group. And not needed to create new group.
var existingFilterGroup = queryPart.FilterGroups[0];
existingFilterGroup.Filters.Add(filterRecord);
Update 2:
To avoid problems with draftable query (and several other potential problems Orchard CMS: Adding default data to fields and then querying them) it is better to move the calling Publish method to the end of your code and other part of your code should be left unchanged. And in your case would be better if you will always publish your query without checking IPublishingControlAspect and Draftable.
Dynamics crm when retrieving value and updating it into another entity it showing like
The Requested Resources was not found or you do not have sufficient permissions to view it
i specified update ids like
enobj.Id=(Guid)context.OutputParameters["id"];
message:create
service :update on another entity
this is my code:
Query Expression query = new Query Expression();
query.EntityName = en.LogicalName;
query.ColumnSet = new ColumnSet("new_amount");
var x = service.RetrieveMultiple(query);
Entity enobj = new Entity("new_product");
int i = 0;
foreach (var item in x.Entities)
{
i = i + (int)item.Attributes["new_amount"];
enobj.Attributes["new_grandtotal"] = i;
}
enobj.Id=(Guid)context.OutputParameters["id"];
// en.Id = enobj.Id;
enobj.Id = en.Id;
service.Update(enobj);
message:create
service :update
i have two entites product and productlineitems
in productlineitems iam creating a record with the field amount 50 after creating that value.iam updating on product entity.
again i create productlineitem 2 with the value some 90.iam adding 50+90 =140
again lineitem 3 with the value. iam taking that on product entity
message:create --- productlineitems
service :update --- product
I think you are trying to update Product with Product Line Id. Try the following:
Replace
enobj.Id = en.Id;
With
// set the field name (key) based on what you got in system
enobj.Id = (Guid)en["new_productid"];
Also, Calling Context is set to Current user. So make sure that user have permissions to update Product.
I am exploring the "QueryExpression" mechanism used to Retrieve data via the Dynamics CRM SDK, and I think I have hit a problem / limitiation with the SDK, but I would like to ascertain that for certain..
Given this desired SQL:
Select C.firstname, C.lastname
FROM contact C
INNER JOIN customeraddress A on C.contactid = A.parentid
WHERE
((C.firstname = 'Max' AND C.lastname = 'Planck') OR (C.firstname = 'Albert' AND C.lastname = 'Einstein'))
OR
A.Line1 = 'The secret moonbase'
I cannot appear to translate the filter criteria above (the where clause) into the equivalent SDK conditions / filterexpressions etc.
As you can see, I want to query:-
contact, joined to customeraddress (thats simple, just add a link entity to the query expression),
where the contact is either Albert Einstein, or Max Planck (Again, that is simple, add FilterExpressions to the QueryExpression)
OR the customeraddress 'line1' equals 'the secret moonbase' (This is the problematic bit, as soon as I append filter criteria to the LinkEntity, Dynamics uses an "AND" conjunction with the criteria / filters on the main entity.
So the problem I have described in point 3 above, means I can't query dynamics for:
(Albert Einstein Or Max Planck) or anyone who lives at the secret moonbase.
Is this is a current limtation of the SDK?
Ok, I have discovered the answer to this, thanks in part to #mwrichardsone who prompted me to explore how the Dynamics Crm Linq query provider does it, I was then able to work backwards from there..
So here is the equivalent Linq query expression which works (I am using the CrmOrganisationServiceContext):-
var contactsQuery = from c in orgService.CreateQuery("contact")
join a in orgService.CreateQuery("customeraddress") on (Guid)c["contactid"] equals (Guid)a["parentid"]
where (((string)c["firstname"] == "Max" && (string)c["lastname"] == "Planck")
|| ((string)c["firstname"] == "Albert" && (string)c["lastname"] == "Einstein"))
|| (string)a["line1"] == "The secret moonbase"
select c;
I then found this article which explains how you can convert linq query to a Query Expression or Fetch Xml: http://pogo69.wordpress.com/2012/04/05/crm-linq-provider-converting-expressions-to-queryexpression-andor-fetchxml/
Once i applied that technique I was able to see what the equivalent QueryExpression looks like.. and basically, the bit that I was missing (key insight) is that when you add a ConditionExpression you can set it's "EntityName". This means you can add a ConditionExpression to a filter group thats on the parent / main entity, even though the condition is actually for an attribute thats present on a link entity (in this case customeraddrress line1). I was assuming you had to add the condition to the linkentity that had that particular attribute - which is also what #Henk van Boeijen did in his answer - and that did not give the correct results.
So the final working QueryExpression looks like this (notice the condition for address line 1 is not added to the address link entity, its added to the filter group on the main entity, and it has an "entity name" set to the alias of the link entity)
var orgService = serviceProvider.GetOrganisationService();
using (orgService as IDisposable)
{
var query = new QueryExpression("contact");
query.ColumnSet.AddColumn("firstname");
query.ColumnSet.AddColumn("lastname");
// so link in customer address.
query.AddLink("customeraddress", "contactid", "parentid", JoinOperator.Inner);
var addressLink = query.LinkEntities[0];
addressLink.EntityAlias = "A";
addressLink.IncludeAllColumns();
// conditions for max planck
var firstName1Condition = new ConditionExpression("firstname", ConditionOperator.Equal, "Max");
var lastname1Condition = new ConditionExpression("lastname", ConditionOperator.Equal, "Planck");
// Groups those conditions using an "AND" conjunction.
var maxPlankFilter = new FilterExpression(LogicalOperator.And);
maxPlankFilter.AddCondition(firstName1Condition);
maxPlankFilter.AddCondition(lastname1Condition);
// conditions for albert einstein
var firstname2Condition = new ConditionExpression("firstname", ConditionOperator.Equal, "Albert");
var lastname2Condition = new ConditionExpression("lastname", ConditionOperator.Equal, "Einstein");
// Groups those conditions using an "AND" conjunction.
var albertEinsteinFilter = new FilterExpression(LogicalOperator.And);
albertEinsteinFilter.AddCondition(firstname2Condition);
albertEinsteinFilter.AddCondition(lastname2Condition);
// could optionally chain the 2 filters so we get Albert's contitions chained (using AND) to max's conditions
// albertEinsteinFilter.AddFilter(maxPlankFilter);
// conditions for address line 1 moonbase
var addressLine1Filter = new FilterExpression(LogicalOperator.And);
var line1Condition = new ConditionExpression("A", "line1", ConditionOperator.Equal, "The secret moonbase");
addressLine1Filter.AddCondition(line1Condition);
// add filters to query
// ensures each filter that we add to our queries criteria is chained together using an OR.
query.Criteria.FilterOperator = LogicalOperator.Or;
query.Criteria.AddFilter(albertEinsteinFilter);
query.Criteria.AddFilter(maxPlankFilter);
query.Criteria.AddFilter(addressLine1Filter);
var results = orgService.RetrieveMultiple(query);
int resultCount = 0;
foreach (var r in results.Entities)
{
resultCount++;
Console.WriteLine(string.Format("{0} {1} {2}", (string)r["firstname"], (string)r["lastname"], (string)((AliasedValue)r["A.line1"]).Value));
}
Console.WriteLine("There were " + resultCount + " results..");
}
Side Note: See #Henk van Boeijen's post below if you would like to see a shorter syntax for building a query expression. If productivity is truly your concern however, I would have to echo the comment from #Nicknow below and suggest that you seriously take a look at using the Linq query mechanism for performing CRM queries.
Also #Henk van Boeijen has pointed out that my answer is based on a feature that only appears in the 2013 SDK, and doesn't appear to be in prior versions. I haven't checked this personally, but that information is probably very useful for you to know especially if you are not using the latest versions of the SDK.
It is actually pretty straightforward; use the LogicalOperator and the LinkEntity.
I would recommend adding the DISTINCT predicate.
private IEnumerable<Entity> QueryExpression(IOrganizationService service)
{
var query = new QueryExpression("contact");
query.Distinct = true;
query.ColumnSet.AddColumns("firstname", "lastname");
query.Criteria.FilterOperator = LogicalOperator.Or;
var f1 = query.Criteria.AddFilter(LogicalOperator.And);
f1.AddCondition("firstname", ConditionOperator.Equal, "Max");
f1.AddCondition("lastname", ConditionOperator.Equal, "Planck");
var f2 = query.Criteria.AddFilter(LogicalOperator.And);
f2.AddCondition("firstname", ConditionOperator.Equal, "Albert");
f2.AddCondition("lastname", ConditionOperator.Equal, "Einstein");
var link = query.AddLink("customeraddress", "contactid", "parentid");
link.EntityAlias = "ca";
query.Criteria.AddCondition("ca", "line1", ConditionOperator.Equal, "The secret moonbase");
var response = service.RetrieveMultiple(query);
return response.Entities;
}
It is important to note that this query uses a new feature added in Dynamics CRM 2013. It does not work in Dynamics CRM 2011, because in that version it is not possible to specify an entityname (or its alias) in the ConditionExpression.
I have written code for retrieving the Opportunity entity from dynamics CRM, is there any way I can retrieve only top five entities based on the revenue ?
QueryExpression query_ = null;
RetrieveMultipleRequest requests_ = null;
query_ = new QueryExpression();
query_.EntityName = "opportunity";
query_.ColumnSet = new ColumnSet(true);
query_.Orders.Add(new OrderExpression("estimatedvalue", OrderType.Descending));
query_.PageInfo.Count = 5;
query_.PageInfo.PageNumber = 1;
requests_ = new RetrieveMultipleRequest();
requests_.Query = query_;
EntityCollection collection = _sdk.RetrieveMultiple(requests);
In query expression you can set
queryExpression.PageInfo.Count = 5;
Don't forget put a specific order, in a FetchXml you can set like that:
<fetch mapping="logical" count="0" version="1.0">
Any idea how to inject values to the Enterprise Keywords column of a List / Doc Lib Item using code?
Tried the following, it didn't give any error, but that column wouldn't update, while the Title did.
using (var site = new SPSite("http://testweb"))
{
using (var web = site.OpenWeb("testsite1"))
{
var list = web.Lists["testlist1"];
var item = list.AddItem();
item["Title"] = string.Format("Injected from code on {0}", DateTime.Now.ToString());
item["Enterprise Keywords"] = "1;#Opera|4eed0518-9676-4afc-be20-9027b3b69e42";
item.Update();
}
}
In this code, Opera keyword has been added previously, I've checked it against the TaxonomyHiddenList list as well using code to extract the correct ID and IdForTerm (the GUID).
What am I missing here?
To add a taxonomy field value the approach is a little bit different. Please try:
TaxonomyField entKeyword = (TaxonomyField)item.Fields["Enterprise Keywords"];
TaxonomyFieldValue term = new TaxonomyFieldValue("1;#Opera|4eed0518-9676-4afc-be20-9027b3b69e42");
entKeyword.SetFieldValue(item,term);
in stead of:
item["Enterprise Keywords"] = "1;#Opera|4eed0518-9676-4afc-be20-9027b3b69e42";