CRM365 - What is the easiest way to get list 1:M entity relations - entity

Is there way (plugin to XrmToolBox, code fragment) to get the list of lookup attributes pointing to my entity? I need exactly the same list as in FetchXML Builder plugin, link-entity Relationship 1:M (see the picture) and be able to copy this list.
(My entity is opportunity)
Thanks for any suggestion.

If you just want the list to copy and paste, you can get this in the browser using CRM's WebAPI
/api/data/v9.0/RelationshipDefinitions/Microsoft.Dynamics.CRM.OneToManyRelationshipMetadata?$select=SchemaName&$filter=ReferencedEntity eq 'account'
This query is doing the following:
Retrieves all 1:N relationships from CRM
Limiting the number of attributes returned to only include Schemaname
Filtering the result to only show attributes targeting the account entity
You just open your CRM organization in the browser and paste the above line after your CRM's address
e.g.
https://myorg.crm.dynamics.com/api/data/v9.0/RelationshipDefinitions/Microsoft.Dynamics.CRM.OneToManyRelationshipMetadata?$select=SchemaName&$filter=ReferencedEntity eq 'account'

As Filburt show me the right way, possible C# solution is in the bottom
public List<KeyValuePair<string, string>> GetRelatedEntities (string entityName)
{
List<KeyValuePair<string, string>> retval = new List<KeyValuePair<string, string>>();
RetrieveEntityRequest retrieveBankAccountEntityRequest = new RetrieveEntityRequest
{
EntityFilters = EntityFilters.All,
LogicalName = entityName
};
RetrieveEntityResponse retrieveBankAccountEntityResponse = (RetrieveEntityResponse)service.Execute(retrieveBankAccountEntityRequest);
OneToManyRelationshipMetadata[] relations = retrieveBankAccountEntityResponse.EntityMetadata.OneToManyRelationships;
foreach(OneToManyRelationshipMetadata m in relations)
{
retval.Add(new KeyValuePair<string, string>(m.ReferencingEntity, m.ReferencingAttribute));
}
return retval;
}

Related

Apache Ignite Continuous Queries : How to get the field names and field values in the listener updates when there are dynamic fields?

I am working on a POC on whether or not we should go ahead with Apache Ignite both for commerical and enterprise use. There is a use case though that we are trying to find an answer for.
Preconditions
Dynamically creation of tables i.e. there may be new fields that come to be put into the cache. Meaning there is no precompiled POJO(Model) defining the attributes of the table/cache.
Use case
I would like to write a SELECT continuous query where it gives me the results that are modified. So I wrote that query but the problem is that when the listener gets a notification, I am not able to find all the field names that are modified from any method call. I would like to be able to get all the field names and field values in some sort of Map, which I can use and then submit to other systems.
You could track all modified field values using binary object and continuous query:
IgniteCache<Integer, BinaryObject> cache = ignite.cache("person").withKeepBinary();
ContinuousQuery<Integer, BinaryObject> query = new ContinuousQuery<>();
query.setLocalListener(events -> {
for (CacheEntryEvent<? extends Integer, ? extends BinaryObject> event : events) {
BinaryType type = ignite.binary().type("Person");
if (event.getOldValue() != null && event.getValue() != null) {
HashMap<String,Object> oldProps = new HashMap<>();
HashMap<String,Object> newProps = new HashMap<>();
for (String field : type.fieldNames()) {
oldProps.put(field,event.getOldValue().field(field));
newProps.put(field,event.getValue().field(field));
}
com.google.common.collect.MapDifference<Object, Object> diff = com.google.common.collect.Maps.difference(oldProps, newProps);
System.out.println(diff.entriesDiffering());
}
}
});
cache.query(query);
cache.put(1, ignite.binary().builder("Person").setField("name","Alice").build());
cache.put(1, ignite.binary().builder("Person").setField("name","Bob").build());

How to Create ViewModel with multiple related tables and Save Form

I am trying to figure out the best way to accomplish this given the modern versions. I have am using VS2012 MVC4 EF5 and have built a edmx file from my database. I built a form that will allow submission of vendor information. The main table is Vendor table that contains mainly contact information and there are additional tables that store their multiple category choices (checkbox list) and another that stores their minority info (collection of radio buttons). So my ViewModel is the vendor table and I populate the checkboxes and radio buttons with view bags that query the lookup tables for their values.
So I assume I should either build the categories and minority parts into the ViewModel and somehow wire up the magic so that the database knows how to save the returned values or should I just use viewbags and then somehow on post read those values and loop through them to store them to the database? Either way I am stuck and don't know how to do this.
I have serached numerous examples online but none of them fit this situation. The is not a complex data model but should be rather common real world situation. I am new to MVC so forgive me if I am missing something obvious.
Any guidance is appreciated.
UPDATE: Here is the baseic code to save the ViewModel to the db but how do you save the checkbox list and radio buttons. I think there are two approaches 1) to somehow include them in the ViewModel or 2) perform a separate function to save the form checkbox and radio button values.
[HttpPost]
public ActionResult Form(VendorProfile newProfile)
{
if (ModelState.IsValid)
{
newProfile.ProfileID = Guid.NewGuid();
newProfile.DateCreated = DateTime.Now;
_db.VendorProfiles.Add(newProfile);
_db.SaveChanges();
return RedirectToAction("ThankYou", "Home");
}
else
{
PopuplateViewBags();
return View(newProfile);
}
}
Perhaps another way of stating my problem is what if you had to build an form to where people would sign up and select all their favorite flavors of ice cream from a list of 31 flavors. You need to save the person's contact information in the primary table and then save a collection of their flavor choices in another table (one-to-many). I have a ViewModel for the contact form and a list of flavors (checkbox list) displayed from a lookup table. How do you write code to save this form?
SOLUTION: There might be a better way, but wanted to post what I discovered. You can pass in the collection of checkboxes and then send them to another method that handles the db inserts.
[HttpPost]
public ActionResult Form(VendorProfile newProfile, int[] categories)
{
if (ModelState.IsValid)
{
newProfile.ProfileID = Guid.NewGuid();
newProfile.DateCreated = DateTime.Now;
_db.VendorProfiles.Add(newProfile);
_db.SaveChanges();
InsertVendorCategories(newProfile.ProfileID, categories);
return RedirectToAction("ThankYou", "Home");
}
else
{
PopuplateViewBags();
return View(newProfile);
}
}
private void InsertVendorCategories(Guid ProfileID, int[] categories)
{
try
{
var PID = new SqlParameter("#ProfileID", ProfileID);
var CID = new SqlParameter("#CatID", "");
foreach (int c in categories)
{
CID = new SqlParameter("#CatID", c);
_db.Database.ExecuteSqlCommand("Exec InsertVendorCategory #ProfileID, #CatID", PID, CID);
}
}
catch { Exception ex; }
}

How to create an ICriterion in NHibernate that filters based on the content of a collection

I have several ICriterion instances that I combine in various ways (conjunction, disjunction, etc.) based on user input. I'm having trouble creating an ICriterion that is based on matching a value in an associated collection.
For example, given a one-to-many relationship between Orders and OrderItems, I want to be able to create an ICriterion that selects all Orders that have an OrderItem with a Quantity > 100.
I've tried several things and haven't yet found anything that works.
i had a the same problem in a project. you need a pair of alias and criteria for each filtered collection.
KeyValuePair<string, ICriterion[]> collectionfilters = GetFromSomeWhere();
foreach (var association in collectionfilters)
{
criteria.CreateAlias(association.Key, association.Key);
foreach(var crit in association.Value)
{
criteria.Add(crit);
}
}
// example
KeyValuePair<string, ICriterion[]> GetFromSomeWhere()
{
return new KeyValuePair<string, ICriterion[]>("OrderItems", new []{ Restrictions.Gt("OrderItems.Quantity", 100) });
}

Simple Delete in Entity Framework using WCF (many to many relationship)

I have a simple database model containing 3 Tables : Companies, Categories and CompanyCategories (which is a relation table with only 2 FK : CompanyID and CategoryID).
My edmx model it only shows Companies and Categories tables (CompanyCategories is somehow hidded since its a simple many to many relationship table).
In the WCF service, I have a GetDatabase() function that returns all the database objets wrapped in one big custom object :
[OperationContract]
public FullDatabase GetDatabase()
{
DBEntities context = new DBEntities ();
FullDatabase mydb = new FullDatabase();
mydb.Companies = context.Companies.ToList();
mydb.Categories = context.Categories.ToList();
return mydb;
}
[OperationContract]
public FullDatabase UpdateDatabase(FullDatabase db)
{
// Here is my problem when removing a category from a company on
// the client its been brought back in my db object
}
class FullDatabase()
{
List<Company> Companies;
List<Category> Categories;
}
On the client now, I use GetDatabaseAsync() to retrieve the database in a _FullDB variable. Now using that variable I tried the following :
// Adding a category like that Works well
Company c = _FullDB.Companies.First();
c.Categories.Add(_FullDB.Categories.First());
wcfServiceClientObject.UpdateDatabaseASync(_FullDB);
.....
// Removing a category, doesn't work though :
Company c = _FullDB.Companies.First();
c.Categories.Remove(_FullDB.Categories.First());
wcfServiceClientObject.UpdateDatabaseASync(_FullDB);
// here my c.Categories.Count is updated correctly to delete the item
// but when on the server after (in the UpdateDatabase function) the item
// I deleted is still there
I really dont understand why the Add would work but not the Remove.
Finally found the problem. Now it works, but I'm not sure it is the best way to do it.
When removing the category from the company, I also had to also remove the company from the category...
Company comp = _FullDB.Companies.First();
Category cat = _FullDB.Categories.First();
comp.Categories.Remove(cat);
cat.Companies.Remove(comp);
wcfServiceClientObject.UpdateDatabaseASync(_FullDB);

Get existing entity if it exists or create a new one

I'm importing data that may or may not exist already in my database. I'd like NHibernate to associate any entities with the existing db one if it exists (probably just setting the primary key/id), or create a new one if it doesn't. I'm using S#arp architecture for my framework (MVC 2, NHibernate, Fluent).
I've added the [HasUniqueDomainSignature] attribute to the class, and a [DomainSignature] attribute to the properties I want to use for comparison. The only way I can think to do it (which is not an acceptable solution and may not even work) is the following (psuedo C#):
foreach (Book importedBook in importedBooks){
foreach (Author author in importedBook.Authors){
if (!author.IsValid()){ // NHibernate Validator will check DomainSignatures
author = _authorRepository.GetByExample(author); // This would be to get the db object with the same signature,
//but I don't think I could even update this as I iterate through it.
}
}
}
As you can see, this is both messy, and non-sensical. Add to that the fact that I've got a half dozen associations on the Book (subject, format, etc), and it doesn't make any sense. There's got to be an easy way to do this that I'm missing. I'm not a novice with NHibernate, but I'm definitely not an expert.
I might not be understanding the problem, but how can the data "may or may not exist in the database"? For example, if a Book has 2 Authors, how is the relationship stored at the database level if the Author doesn't exist?
It seems as if you're trying to use NHibernate to import your data (or create an entity if it doesn't exist) which doesn't seem correct.
Most database implementations support a conditional UPDATE-or-INSERT syntax. Oracle, for example, has a MERGE command. In combination with a Hibernate <sql-insert> block in your mapping you should be able to work something out. I don't know Fluent but I assume it supports this too.
Just realize I never gave an answer or approved another's answer. I ended up just writing a new SaveOrUpdate which takes a parameter to check for existing before persisting. I also added an attribute to my domain models to overwrite when saving/updating (although in retrospect it's only on updating that it'd be overwriting).
Here's the code if it can help anyone else in this dilemma:
public TEntity SaveOrUpdate<TEntity>(TEntity entity, bool checkForExistingEntity)
{
IRepository<TEntity> repository = new Repository<TEntity>();
if (checkForExistingEntity) {
if (entity is Entity) {
IEnumerable<PropertyInfo> props = (entity as Entity).GetSignatureProperties();
Dictionary<string, object> parameters =
props.ToDictionary(propertyInfo => propertyInfo.Name, propertyInfo => propertyInfo.GetValue(entity, null));
TEntity duplicateEntity = repository.FindOne(parameters);
if (duplicateEntity != null) {
// Update any properties with the OverwriteOnSaveUpdate attribute
foreach (var property in RepositoryHelper.GetUpdatableProperties(typeof(TEntity)))
{
object initialValue = property.GetValue(entity, null);
property.SetValue(duplicateEntity, initialValue, null);
}
// Fill in any blank properties on db version
foreach (var property in typeof(TEntity).GetProperties())
{
if (property.GetValue(duplicateEntity, null) == null) {
object initialValue = property.GetValue(entity, null);
property.SetValue(duplicateEntity, initialValue, null);
}
}
return duplicateEntity;
}
}
}
return SaveOrUpdate(entity);
}