CRM 2013 retrieve related entities using LINQ? - microsoft-dynamics

I'm retrieving account entities using code like this:-
var connection = CrmConnection.Parse(ConnectionString);
using (var orgService = new OrganizationService(connection))
{
var context = new MyOrganizationServiceContext(orgService);
var accounts = context.AccountSet.Where(...);
}
None of the returned accounts' relationship properties are populated (understandable, as this could result in lots of data being retrieved). Is there any way of requesting that certain relationships be populated, either as part of the LINQ query, or afterwards (e.g. on an entity-by-entity basis)?

you have a couple of options. Here the relevant MSDN article:
Access entity relationships

Related

Search custom property in SharePoint User Profile

I created a custom property in the user profile.
I want to search through all the user profiles and output those profiles in which the custom property contains a certain string
For example:
User1- Custom Property value is 1,2,3
User2- Custom Property value in 2,4,5
User3- Custom Property value is 4,6,8
I want to output all the profiles in which Custom Property contains 2
(using c# code)
So the output should have User1 and User2
Can someone suggest the best way to implement this?
I did find some links in the internet for searching user profiles use KeyWord search but and not sure if those methods could be used to search through Custom Properties.
Example: https://www.collaboris.com/how-to-use-search-keywordquery-to-query-user-profiles-in-sharepoint/
I am using SharePoint 2013
We ended up promoting the Custom Property that we added to the User profile to a Managed property.
Also it seems like we can do wildcard searches on managed properties so we do People searches like "CustomProperty:*,2,*" so that it would return all the user profiles which have the number 2 in the custom property of their user profile
Interestingly the wildcard works only on the end for OOTB properties like FirstName so we cant do things like FirstName:oh and expect it would return John Doe's profile
But we can certainly do this - FirstName:joh* and that would return all the people whose first name starts with Joh (which would include John Doe)
But it seems like the wildcard works both at the beginning and the end for the custom managed properties (which helped a great deal for us)
On how to return the results of the search using c# we used this-
private DataTable GetPeople(SPSite spSite, string queryText)
{
var keywordQuery = new KeywordQuery(spSite)
{
QueryText = queryText,
KeywordInclusion = KeywordInclusion.AllKeywords,
SourceId = System.Guid.Parse("b09a7990-05ea-4af9-81ef-edfab16c4e31")
};
keywordQuery.RowLimit = this.MaxProfilesToDisplay;
keywordQuery.SelectProperties.Add("AccountName");
keywordQuery.SelectProperties.Add("PictureURL");
SearchExecutor e = new SearchExecutor();
ResultTableCollection rt = e.ExecuteQuery(keywordQuery);
var tab = rt.Filter("TableType", KnownTableTypes.RelevantResults);
var result = tab.FirstOrDefault();
DataTable DT = result.Table;
return DT;
}
and we would invoke this like
DataTable dt = GetPeople(SPContext.Current.Site, "CustomProperty:*,2,*" );

How to query based on one-to-many relationships in Spring Data Neo4j

I have defined simple one-to-many relationship as:
#Relationship(type = "BELONG")
private Set<Category> categories;
I want to query all the objects based on the exact set of Category. i.e. implement something like:
Page<SomeObject> findAllByCategories(Set<Category> categories, PageRequest page);
What is the best way to do it in Spring Data Neo4j?
You have a couple of options on how you can do this.
Your calling code can simply call the following on your SomeObjectRepository:
Iterable<Long> ids = categories.stream().map(SomeObject::getId).collect(Collectors.toSet());
Iterable<SomeObject> someObjects = someObjectRepository.findAll(ids, 1);
Note this method does not support paging though.
Another way is to inject a Session into your calling code and either write a custom Cypher query to retrieve the objects you want or use the load all by instance method:
#Autowired
private Session session;
...
// Option 1: write some cypher
Map<String, Object> params = new HashMap<>():
params.put("ids", ids) // use a stream like above to collect the ids.
Iterable<SomeObject> someObjects = session.query(SomeObject.class, "MATCH (n:SomeObject) ...", params);
//Option 2: use the load by instances method which also allows pagination:
Collection<SomeObject> someObjects = session.loadAll(categories, new Pagination(0, 25));
My recommendation would be option 2 as it pretty much does exactly what you want.

Sitecore WFFM: Issues Submitting form programmatically

I have been trying to submit a my own form to WFFM. The form I created is identical to the one created with WFFM, that way all fields map correctly.
I began following the following steps: https://jermdavis.wordpress.com/2015/05/18/programmatic-wffm-submissions/
I had to make minor changes to the code in order to get the SubmitActionManager to work
The members of Sitecore.Form.Core.Submit.SubmitActionManager class
have been moved to the IActionExecutor interface.To obtain the
instance of this interface use the
(IActionExecutor)Factory.CreateObject ("wffm/wffmActionExecutor",
false) call.
Below is the code I have so far:
public void SubmitData(ContactUsFormModel data)
{
var results = new List<ControlResult>();
results.Add(makeControlResult(Models.Constants._cufFirstNameID, "First Name", data.FirstName));
results.Add(makeControlResult(Models.Constants._cufLastNameID, "Last Name", data.LastName));
results.Add(makeControlResult(Models.Constants._cufEmailID, "Email", data.Email));
results.Add(makeControlResult(Models.Constants._cufCompanyID, "Company", data.Company));
results.Add(makeControlResult(Models.Constants._cufSubjectID, "Subject", data.Subject));
results.Add(makeControlResult(Models.Constants._cufMessageID, "Message", data.Message));
var formItem = Sitecore.Context.Database.GetItem(Models.Constants._contactUsFormID);
var simpleForm = new SitecoreSimpleForm(formItem);
var saveActionXml = simpleForm.FormItem.SaveActions;
var actionList = Sitecore.Form.Core.ContentEditor.Data.ListDefinition.Parse(saveActionXml);
var actionDefinitions = new List<ActionDefinition>();
actionDefinitions.AddRange(actionList.Groups.SelectMany(x => x.ListItems).Select(li => new ActionDefinition(li.ItemID, li.Parameters) { UniqueKey = li.Unicid }));
var SubmitActionManager = (IActionExecutor)Factory.CreateObject("wffm/wffmActionExecutor", false);
Sitecore.Form.Core.WffmActionEvent sessionID = new Sitecore.Form.Core.WffmActionEvent();// SessionIDGuid
var result = SubmitActionManager.ExecuteSaving(ID.Parse(Models.Constants._contactUsFormID), results.ToArray(), actionDefinitions.ToArray(), true, ID.Parse( sessionID.SessionIDGuid ));
}
private ControlResult makeControlResult(string fieldID, string fieldName, string fieldValue)
{
return new ControlResult(fieldName, fieldValue, string.Empty)
{
FieldID = fieldID,
FieldName = fieldName,
Value = fieldValue,
Parameters = string.Empty
};
}
I wasnt sure where to get Sitecore.Form.Core.Analytics.AnalyticsTracker.SessionId from to use it inside ExecuteSaving, so I used WffmActionEvent.
Also the guide I followed uses Execute, which is now deprecated, so I had to go with ExecureSaving (my best guess).
This however doesn't seem to be posting the submitted data into the databse. I am unable to see any of my submissions inside WFFM Form Reports or inside mongoDB.
The logs however state that the form is being saved to the database, not sure what the other warnings mean.
24688 17:20:39 WARN [WFFM] Tracker.Current is not initialized
24688 17:20:39 INFO AUDIT (sitecore\admin): [WFFM] Form {978DBF4C-0F56-45A8-A9AC-52EF8D995DDF} is saving to db
24688 17:20:39 WARN [WFFM] Tracker.Current.Contact is not initialized
24688 17:20:39 WARN [WFFM] Tracker.Current.Interaction is not initialized
24688 17:20:39 WARN [WFFM] CurrentSession is not initialized
As you are using Sitecore 8 the form submission is stored in MongoDB. Sitecore's implementation of MongoDB, xDB mostly relies on tracking users, calling them Contacts.
Most data stored in xDB is linked to a Contact via a ContactId. The error messages you are finding in the log are stating that tracking is currently not enabled, therefore no Contact is present and there is no Interaction between the site and user.
Therefore you need to start Sitecore.Tracker I recommend using the following code
if (!Tracker.IsActive)
Tracker.StartTracking();
if (!Tracker.IsActive || Tracker.Current.Contact == null)
{
// handle no tracker and contact
}
Now that you have tracking working you need to use the correct ID for your sessionID variable.
The blog you are following is based on Sitecore 7, in Sitecore 8 Sitecore.Form.Core.Analytics.AnalyticsTracker.SessionId is removed. I decompiled the Sitecore 7 code and Sitecore.Form.Core.Analytics.AnalyticsTracker.SessionId ultimately uses Tracker.CurrentVisit.VisitId.
However this namespace has changed in Sitecore 8, Visits are now called interactions so instead of your variable SessionID you will want to use
Tracker.Current.Interaction.InteractionId;
That should resolve the issue you are currently having but you may need a bit more development to finish it off.

How to search for Items that doesn't contain certain keywords using Sitecore Advanced Database Crawler?

I have millions of items in the database. And user can search those items based on the keyword. In the search function, I need to provide a feature that search for NOT that keyword.
For example Item A has a field called msg and the value is Sitecore is awesome and great.
In the search box, user can check the checkbox that indicates to show any item that doesn't contain the keyword. Maybe user key in is keyword, so Item A will not be displayed or retrieved by ADC.
Edit: Currently I'm using sitecore6.6, thus Search method has been deprecated. I have tried the Not keyword by using Occurrence.MustNot, but it doesn't return any result.
The Sitecore Advanced Database Crawler is an extension of the Sitecore.Search API and Sitecore.Search API is a wrapper around Lucene.
In Lucene you can user queries with NOT or - to exclude something like "Sitecore NOT awesome" or "Sitecore -awesome".
To exclude something you need at least one include term.
Not sure if it works, but give it a try.
This is untested, but you might have luck by using a MatchAllDocsQuery and supplying the keywords in the form of a Filter.
BooleanQuery booleanQuery = new BooleanQuery();
QueryParser queryParser = new QueryParser("msg", new StandardAnalyzer());
Query userQuery = queryParser.Parse("Sitecore is awesome and great");
booleanQuery.Add(userQuery, reverseQuery.Checked ? BooleanClause.Occur.MUST_NOT : BooleanClause.Occur.MUST);
MatchAllDocsQuery matchAllQuery = new MatchAllDocsQuery();
Filter filter = new QueryFilter(booleanQuery);
using (QueryRunner queryRunner = new QueryRunner("myIndex"))
{
var skinnyItems = queryRunner.RunQuery(matchAllQuery, filter, ...)
}
What I have done to NOT include the keywords associated with the result item set is this:
protected List<Item> getSearchResults(string queryToSearch, string selectedFilter, string notToSearch)
{
Database db = Sitecore.Context.Database;
var index = SearchManager.GetIndex("siteSearchIndexName");
using (SortableIndexSearchContext context = new SortableIndexSearchContext(index))
{
if (!String.IsNullOrWhiteSpace(query))
{
query.ToLower();
CombinedQuery cq = new CombinedQuery();
QueryBase qbKeyword = new FieldQuery("_orderkeywordpair", query);
QueryBase qbContent = new FieldQuery("_content", query);
QueryBase qbHtml = new FieldQuery("html", query);
if (!String.IsNullOrWhiteSpace(selectedFilter) && selectedFilter.ToLower() != "all")
{
QueryBase qbFilter = new FieldQuery("_pagetype", selectedFilter);
cq.Add(qbFilter, QueryOccurance.Must);
}
cq.Add(qbKeyword, QueryOccurance.Should);
cq.Add(qbContent, QueryOccurance.Must);
cq.Add(qbHtml, QueryOccurance.MustNot);
SearchHits hits = context.Search(cq);

Multiple TemplateIds not working in Sitecore's Advanced Database Crawler

I have a "Featured" widget to lead visitors to items I want to feature on certain pages. So I'm trying to get Alex Shyba's Advanced Database Crawler for Sitecore to return all the items that refer to the context item. If I put in one template ID, it works fine. But if I pipe delimit the two templates, I never get a result. What am I doing wrong?
var searchParam = new MultiFieldSearchParam()
{
Database = Sitecore.Context.Database.Name,
Language = Sitecore.Context.Language.Name,
TemplateIds = "{E5B41848-3C07-4F17-84A5-C2C29AD43CAE}|{0C2E35D7-C4C9-478B-B4AB-DE8C2A00908B}"
};
var refinements = new List<MultiFieldSearchParam.Refinement>();
refinements.Add(new MultiFieldSearchParam.Refinement("pages", contextItemGUID));
searchParam.Refinements = refinements;
var runner = new QueryRunner("web");
foreach (var skinnyItem in runner.GetItems(searchParam))
{
yield return skinnyItem.GetItem();
}
Again, if I make that TemplateIds a single GUID (either one), it works as expected, but just returning, obviously, items of the specified template.
As Mark notes, it's a bug in the ADC. Our solution was to refactor the ApplyTemplateFilter method as follows:
protected void ApplyTemplateFilter(CombinedQuery query, string templateIds, QueryOccurance occurance)
{
ApplyIdFilter(query, BuiltinFields.Template, templateIds, occurance);
}