I am using this code to retrieve global optionsets
var request = new RetrieveOptionSetRequest {Name = "OptionsetNameGoesHere"};
var retrieveOptionSetResponse =(RetrieveOptionSetResponse) DynamicsHandler._serviceProxy.Execute(request);
var retrievedOptionSetMetadata =(OptionSetMetadata) retrieveOptionSetResponse.OptionSetMetadata;
var optionList = retrievedOptionSetMetadata.Options.ToArray();
foreach (var optionMetadata in optionList)
{
Printout(optionMetadata.Label.LocalizedLabels[0].Label + "\n");
}
But how do I retrieve optionsets like AccountCategory (AccountCategoryCode) so that I can bind them to a Combobox?
You should get it with a RetrieveAttributeRequest. It will return an RetrieveAttributeResponse which contains the Property AttributeMetadata.
In your case it should be of type OptionSetMetadata, which is what you are looking for.
This is how I have solved this problem.
CRMBase is my base class with connection to the CRM instance. Codelanguage: C#
public static Dictionary<int, string> GetAll(CRMBase conn, string entityName, string attributeName)
{
OptionMetadataCollection result = RetrieveOptionSetMetaDataCollection(conn, entityName, attributeName);
return result.Where(r => r.Value.HasValue).ToDictionary(r => r.Value.Value, r => r.Label.UserLocalizedLabel.Label);
}
// Method to retrieve OptionSet Options Metadadata collection.
private static OptionMetadataCollection RetrieveOptionSetMetaDataCollection(CRMBase conn, string prmEntityName, string prmAttributeName)
{
RetrieveEntityRequest retrieveEntityRequest = new RetrieveEntityRequest();
retrieveEntityRequest.LogicalName = prmEntityName;
retrieveEntityRequest.EntityFilters = Microsoft.Xrm.Sdk.Metadata.EntityFilters.Attributes;
RetrieveEntityResponse retrieveEntityResponse = (RetrieveEntityResponse)conn._orgContext.Execute(retrieveEntityRequest);
return (from AttributeMetadata in retrieveEntityResponse.EntityMetadata.Attributes where
(AttributeMetadata.AttributeType == AttributeTypeCode.Picklist & AttributeMetadata.LogicalName == prmAttributeName)
select ((PicklistAttributeMetadata)AttributeMetadata).OptionSet.Options).FirstOrDefault();
}
Related
var kusto = string.Format("let MyData = CompanyMydata" +
" | where ID == 'Z123' | top 1 by dateTimeUtc desc");
var reader = client.ExecuteQuery(kusto);
while (reader.Read())
{
//how can i return coming result as list of string or json string?
}
In while loop I can able to return single column value one by one by using
string state = reader.GetString(1); but i want to return complete result instead of one by one column value.
so that i can do JsonConvert.DeserializeObject<T>(resultString); to specific class.
assuming you're using the client libraries mentioned here, you should be able to do something like the following:
static void Main(string[] args)
{
var kcsb = new KustoConnectionStringBuilder("https://help.kusto.windows.net").WithAadUserPromptAuthentication();
var databaseName = "Samples";
using (var queryProvider = KustoClientFactory.CreateCslQueryProvider(kcsb))
{
var clientRequestProperties = new ClientRequestProperties() { ClientRequestId = "Sample;" + Guid.NewGuid() };
var query = "StormEvents | summarize count(), max(EndTime) by State";
var result = queryProvider.ExecuteQuery<MyType>( // focus on this part
databaseName,
query,
clientRequestProperties)
.ToList();
foreach (var row in result)
{
Console.WriteLine($"State = {row.State}, Count = {row.Count}, MaxEndTime = {row.MaxEndTime}");
}
}
}
class MyType
{
public string State;
public long Count;
public DateTime MaxEndTime;
}
I am a C# developer new to Neo4j. I have spent a couple of weeks learning the graph concept and trying out Cypher. It is so far a good experience!
I now tried to work with some real data from code through the official C# driver. I was surprised to find that the driver is merely a wrapper of the APIs with no real .Net functionality on top.
When creating nodes I managed fine to create Cypher statements with this pattern:
CREATE (:Movie {tmdbId: {tmdbId}, imdbId: {imdbId}, title: {title}, originalTitle: {originalTitle}, collectionInfo: {collectionInfo}, genres: {genres}, releaseDate: {releaseDate}, plot: {plot}, tagline: {tagline}, originalLanguage: {originalLanguage}, tmdbPopularity: {tmdbPopularity}, tmdbVoteAverage: {tmdbVoteAverage}, tmdbVoteCount: {tmdbVoteCount}, budget: {budget}} )
Parameter collection is automatically generated from object. It works fine. But when creating relations I get an unexpected error.
This is the statement I use to create relations. Source and target nodes are looked up by Id.
MATCH (s:Person), (t:Movie) WHERE s.personId=35742 AND t.movieId=19404 CREATE (s)-[r:ACTED_IN {order: {order}, character: {character}}]->(t) RETURN r
The error I receive is:
System.Reflection.TargetParameterCountException: 'Parameter count mismatch.'
The parameter collection is created the same way as last time. It holds two properties named "order" and "character" as expected.
Is there some error in the statement that I am missing?
/// <summary>
/// Add object as node in Neo4j database.
/// All public properties will automatically be added as properties of the node.
/// </summary>
/// <param name="obj">Generic POCO object</param>
/// <param name="label">Specify type name to be uses. Skip if you are satisfied with object type name.</param>
public void AddNode(object obj, string label = null)
{
using (var session = _driver.Session())
{
label = label ?? obj.GetType().Name;
var parameters = GetProperties(obj);
var valuePairs = string.Join(", ", parameters.Select(p => $"{p.Key}: {{{p.Key}}}"));
var statement = $"CREATE (:{label} {{{valuePairs}}} )";
var result = session.Run(statement, parameters);
Debug.WriteLine($"{result.Summary.Counters.NodesCreated} {label} node created with {result.Summary.Counters.PropertiesSet} properties");
}
}
public void AddRelation(string sourceNodeName, string sourceIdName, string targetNodeName, string targetIdName, string relationName, object relation, string relationSourceIdName, string relationPropertyIdName)
{
using (var session = _driver.Session())
{
//MATCH(s:Person), (t:Person)
//WHERE s.name = 'Source Node' AND t.name = 'Target Node'
//CREATE(s) -[r:RELTYPE]->(t)
//RETURN r
var parameters = GetProperties(relation);
var sourceId = parameters[relationSourceIdName];
var targetId = parameters[relationPropertyIdName];
var properties = parameters.Where(p => p.Key != relationSourceIdName && p.Key != relationPropertyIdName).ToList();
var valuePairs = string.Join(", ", properties.Select(p => $"{p.Key}: {{{p.Key}}}"));
var statement = $"MATCH (s:{sourceNodeName}), (t:{targetNodeName}) WHERE s.{sourceIdName}={sourceId} AND t.{targetIdName}={targetId} CREATE (s)-[r:{relationName} {{{valuePairs}}}]->(t) RETURN r";
var result = session.Run(statement, properties);
Debug.WriteLine($"{result.Summary.Counters.RelationshipsCreated} {relationName} relations created with {result.Summary.Counters.PropertiesSet} properties");
}
}
private static Dictionary<string, object> GetProperties(object obj)
{
var dictionary = new Dictionary<string, object>();
foreach (var property in obj.GetType().GetProperties())
{
var propertyName = property.Name;
var value = property.GetValue(obj);
var array = value as string[];
if (array != null)
{
value = string.Join(",", array);
}
if (value is DateTime)
{
var dateTime = (DateTime)value;
value = dateTime.ToString("yyyy-MM-dd");
}
dictionary.Add(propertyName.ToCamelCase(), value);
}
return dictionary;
}
Bruno set me in the right direction! It was not a problem with neither Cypher nor the wrapper. My mistake was to filter the parameters collection and return a property list instead of keeping it as a dictionary.
The adjusted working method now looks like this:
public void AddRelation(string fromNodeName, string fromIdName, string toNodeName, string toIdName, string relationName, object relation, string relationFromIdName, string relationToIdName)
{
using (var session = _driver.Session())
{
//MATCH(s:Person), (t:Person)
//WHERE s.name = 'Source Node' AND t.name = 'Target Node'
//CREATE(s) -[r:RELATIONTYPE]->(t)
//RETURN r
var parameters = GetProperties(relation);
var fromIdValue = parameters[relationFromIdName];
var toIdValue = parameters[relationToIdName];
var properties = parameters.Where(p => p.Key != relationFromIdName && p.Key != relationToIdName).ToDictionary(p => p.Key, p => p.Value);
var valuePairs = string.Join(", ", properties.Select(p => $"{p.Key}: {{{p.Key}}}"));
var statement = $"MATCH (s:{fromNodeName}), (t:{toNodeName}) WHERE s.{fromIdName}={fromIdValue} AND t.{toIdName}={toIdValue} CREATE (s)-[r:{relationName} {{{valuePairs}}}]->(t) RETURN r";
var result = session.Run(statement, properties);
Console.WriteLine($"{result.Summary.Counters.RelationshipsCreated} {relationName} relations created with {result.Summary.Counters.PropertiesSet} properties");
}
}
I'm querying a SharePoint 2013 Term Store via the SharePoint Client Object Model in order to get a TermCollection.
I'd like to bind the results to a WPF TreeView control. Any idea how I can turn the TermCollection into something that the TreeView will understand?
public static TermCollection GetTaxonomyTerms(string webUrl, string libraryTitle, string fieldTitle)
{
var context = new ClientContext(webUrl);
var web = context.Web;
var list = web.Lists.GetByTitle(libraryTitle);
var fields = list.Fields;
var field = context.CastTo<TaxonomyField>(fields.GetByInternalNameOrTitle(fieldTitle));
context.Load(field);
var termStores = TaxonomySession.GetTaxonomySession(context).TermStores;
context.Load(termStores);
context.ExecuteQuery(); // TODO: Can this ExecuteQuery be avoided by using a LoadQuery statement?
var termStore = termStores.Where(t => t.Id == field.SspId).FirstOrDefault();
var termSet = termStore.GetTermSet(field.TermSetId);
var terms = termSet.GetAllTerms(); //TODO: Do we need a version that returns a paged set of terms? or queries the server again when a node is expanded?
context.Load(terms);
context.ExecuteQuery();
return terms;
}
I ended up writing my own code (please let me know if there's an easier way to do this).
My 'Term' object below is just a simple POCO with Name and Terms.
var terms = SharePointHelper.GetTaxonomyTerms(webUrl, libraryTitle, fieldTitle);
var term = terms.AsRootTreeViewTerm();
....
}
public static Term AsRootTreeViewTerm(this SP.TermCollection spTerms)
{
var root = new Term();
foreach (SP.Term spTerm in spTerms)
{
List<string> names = spTerm.PathOfTerm.Split(';').ToList();
var term = BuildTerm(root.Terms, names);
if (!root.Terms.Contains(term))
root.Terms.Add(term);
}
return root;
}
static Term BuildTerm(IList<Term> terms, List<string> names)
{
Term term = terms.Where(x => x.Name == names.First())
.DefaultIfEmpty(new Term() { Name = names.First() })
.First();
names.Remove(names.First());
if (names.Count > 0)
{
Term child = BuildTerm(term.Terms, names);
if (!term.Terms.Contains(child))
term.Terms.Add(child);
}
return term;
}
first time i'm using MongoDB.
I have read this example:
SELECT a,b FROM users WHERE age=33
db.users.find({age:33}, {a:1,b:1})
But I can't translate it into C#. Can anyone help me?
I have translated your query below using the new C# driver (2.2)
var mongoClient = new MongoClient(""mongodb://127.0.0.1:27017"");
var database = mongoClient.GetDatabase("databaseName");
IMongoCollection<Users> _collection = database.GetCollection<Users>("Users");
var condition = Builders<Users>.Filter.Eq(p => p.age, 33);
var fields = Builders<Users>.Projection.Include(p => p.a).Include(p => p.b);
var results= _collection.Find(condition).Project<Users>(fields).ToList().AsQueryable();
You can do it using SetFields method of MongoCursor class, below full example:
var server = MongoServer.Create(connectionString);
var db = _server.GetDatabase("dbName");
var users = db.GetCollection("users");
var cursor = users.FindAs<DocType>(Query.EQ("age", 33));
cursor.SetFields(Fields.Include("a", "b"));
var items = cursor.ToList();
you can use anonymous class
public class User
{
public int age;
public string a;
public string b;
}
var collection = db.GetCollection<User>("Users");
var results = collection.Find(Builders<User>.Filter.Eq(user => user.age, 33))
.Project(u => new { u.a, u.b }).ToList();
//create user class
//(not sure how your class looks like)
public class User
{
public int age;
public string a;
public string b;
}
//then you can use LINQ easily
var server = MongoServer.Create(connectionString);
var db = server.GetDatabase("dbName");
var usersCollection = db.GetCollection<User>("users");
var filteredCollection = usersCollection.AsQueryable().Where(x=> x.age < 33).Where(x=> x.a != null).Contains(x=> x.b != null);
In Dynamics CRM 2011, on the Incident entity, the "Status Reason" optionset (aka statuscode) is related to the "Status" optionset (aka statecode)
e.g. see this screenshot
When I use the API to retrieve the Status Reason optionset, like so:
RetrieveAttributeRequest attributeRequest = new RetrieveAttributeRequest
{
EntityLogicalName = "incident",
LogicalName = "statuscode",
RetrieveAsIfPublished = true
};
RetrieveAttributeResponse attributeResponse = (RetrieveAttributeResponse)serv.Execute(attributeRequest);
AttributeMetadata attrMetadata = (AttributeMetadata)attributeResponse.AttributeMetadata;
StatusAttributeMetadata statusMetadata = (StatusAttributeMetadata)attrMetadata;
var dict = new Dictionary<int?, string>();
foreach (OptionMetadata optionMeta in statusMetadata.OptionSet.Options)
{
dict.Add(optionMeta.Value, optionMeta.Label.UserLocalizedLabel.Label);
}
It works in that I get the whole list of "Status Reason" (statuscode) options. However, I dont get any info about which "Status Reason" (statuscode) options relate to which "Status" (statecode) options.
How do I get that information?
You already have everything try insert this code inside of foreach:
int stateOptionValue = (int)((StatusOptionMetadata)optionMeta).State;
See StatusAttributeMetaData.OptionSet.Options hierarchy can return a type called StatusOptionMetadata if you use the State property of the StatusOptionMetadata, it will return the statecode this statuscode belongs to.
Here is how you can get it by querying the database
SELECT distinct e.LogicalName as entity,
smState.Value AS stateCode,
smstate.AttributeValue,
smStatus.Value AS [statuscode/statusreason],
smStatus.AttributeValue
FROM StatusMap sm
JOIN Entity e ON sm.ObjectTypeCode = e.ObjectTypeCode
JOIN StringMap smState ON smState.AttributeValue = sm.State
AND smState.ObjectTypeCode = e.ObjectTypeCode
AND smState.AttributeName = 'StateCode'
JOIN StringMap smStatus ON smStatus.AttributeValue = sm.Status
AND smStatus.ObjectTypeCode = e.ObjectTypeCode
AND smStatus.AttributeName = 'StatusCode'
WHERE e.LogicalName in ('lead')
ORDER BY e.LogicalName,
smState.AttributeValue,
smStatus.AttributeValue;
Here is working code that will output State/Status mapping for a given entity (you just need to provide the orgServiceProxy):
var dictState = new Dictionary<int, OptionMetadata>();
var dictStatus = new Dictionary<int, List<OptionMetadata>>();
string entityName = "lead";
int count=0;
using (var orgServiceProxy = GetOrgServiceProxy(orgServiceUriOnLine))
{
RetrieveAttributeResponse attributeResponse = GetAttributeData(orgServiceProxy, entityName, "statecode");
AttributeMetadata attrMetadata = (AttributeMetadata)attributeResponse.AttributeMetadata;
StateAttributeMetadata stateMetadata = (StateAttributeMetadata)attrMetadata;
foreach (OptionMetadata optionMeta in stateMetadata.OptionSet.Options)
{
dictState.Add(optionMeta.Value.Value,optionMeta);
dictStatus.Add(optionMeta.Value.Value,new List<OptionMetadata>());
}
attributeResponse = GetAttributeData(orgServiceProxy, entityName, "statuscode");
attrMetadata = (AttributeMetadata)attributeResponse.AttributeMetadata;
StatusAttributeMetadata statusMetadata = (StatusAttributeMetadata)attrMetadata;
foreach (OptionMetadata optionMeta in statusMetadata.OptionSet.Options)
{
int stateOptionValue = ((StatusOptionMetadata)optionMeta).State.Value;
var statusList = dictStatus[stateOptionValue];
statusList.Add(optionMeta);
count++;
}
}
Console.WriteLine($"Number of mappings: {count}");
foreach (var stateKvp in dictState.OrderBy(x=> x.Key))
{
Console.WriteLine($"State: {stateKvp.Value.Value}: {stateKvp.Value.Label.UserLocalizedLabel.Label}");
var statusList = dictStatus[stateKvp.Key];
Console.WriteLine($"\tStatuses");
foreach (var status in statusList.OrderBy(s => s.Value))
{
Console.WriteLine($"\t\t{stateKvp.Value.Value}: {status.Label.UserLocalizedLabel.Label}");
}
}