How do I add a set of strings to an Entity? - dynamics-crm-2011

This is a simple requirement: I want to add a set of strings to Accounts in Dynamics 2011. The string are external IDs for other systems. All the strings should be unique accross all entities.
The only way I can see to do this is define the strings as entities (say 'ExternalCode') and set up a 1:N reslationship between Account and ExternalCode, but this seems incredibly overweight. Also, defining as an entity insists thhat I give the 'ExternalCode' a name, which it obviously doesn't have.
What's the best way to implement this?
Thank you
Ryan

It may seem overweight, but think about entities as if it were tables. Would you create a second table inside MS SQL? If so, then you should create another entity. CRM is very well optimized so I wouldn't worry about this additional overhead.
Alternatively, you could always carry the GUID in the other system.

How are these unique references entering your CRM system. Are you importing the data from each of the external systems? If so I assume the references are unique in the external system? Once imported you want to make sure that any of these references are not duplicated?
Additionally, how many strings are we talking about here? If it is a small number then it would make sense to just define attributes to manage them and check for duplicates in one of the following ways:-
1) Some javascript could be used to make an oData query to confirm the 'uniqueness' of your external reference number before the record is commited. (But, this is not sufficient is records will be created programmatically in the system also).
2) A plug-in which fires on pre-create to again query the system for other records which match the same unique reference numbers and handles the event of a match accordingly.
However, if there are many of them then it may make more sense to define a separate entity as you say and then as above you could associate a new 'reference record' with the entity via a plug-in, but again, check if the record already exists and then either handle an exception or merely associate with an existing record if that is appropriate.
I think they key is what you want to do if you do find a duplicate and how these records are going to be created in the system (e.g. via UI or programmatically or potentially both).
Happy to provide some more assistance if you have some more details.

Related

Reuse same database tables in different repositories (repositories overlap on the data they access)

Suppose I have database tables Customer, Order, Item. I have OrderRepository that accesses, directly with SQL/my ORM, both the Order and Items table. E.g. I could have a method, getItems on the OrderRespositry that returns all items of that order.
Suppose I now also create ItemRepository. Given I now have 2 repositories accessing the same database table, is that generally considered poor design? My thinking is, sometimes a user wants to update the details about an Item (e.g. name), but when using the OrdersRepository, it doesn't really make sense to not be able to access the items directly (you want to know about all the items in an order)
Of course, the OrderRepository could internally create* an ItemRepository and call methods like getItemsById(ids: string[]). However, consider the case that I want to get all orders and items ever purchased by a Customer. Assuming you had the orderIds for a customer, you could have a getOrders(ids: string[]) on the OrderRepository to fetch all the orders and then do a second query to fetch all the Items. I feel you make your life harder (and less efficient) in the sense you have to do the join to match items with orders in the app code rather than doing a join in SQL.
If it's not considered bad practice, is there some kind of limit to how much overlap Repositories should have with each other. I've spent a while trying to search for this on the web, but it seems all the tutorials/blogs/vdieos really don't go further than 1 table per entity (which may be an anti-pattern).
Or am I missing a trick?
Thanks
FYI: using express with TypeScript (not C#)
is a repository creating another repository considered acceptable. shouldn't only the service layer do that?
It's difficult to separate the Database Model from the DDD design but you have to.
In your example:
GetItems should have this signature - OrderRepostiory.GetItems(Ids: int[]) : ItemEntity. Note that this method returns an Entity (not a DAO from your ORM). To get the ItemEntity, the method might pull information from several DAOs (tables, through your ORM) but it should only pull what it needs for the entity's hydration.
Say you want to update an item's name using the ItemRepository, your signature for that could look like ItemRepository.rename(Id: int, name: string) : void. When this method does it's work, it could change the same table as the GetItems above but note that it could also change other tables as well (For example, it could add an audit of the change to an AuditTable).
DDD gives you the ability to use different tables for different Contexts if you want. It gives you enough flexibility to make really bold choices when it comes the infrastructure that surrounds your domain. So ultimately, it's a matter of what makes sense for your specific situation and team. Some teams would apply CQRS and the GETOrder and Rename methods will look completely different under the covers.

How to use Azure Search Service with heterogenous data sources

I have worked on Azure Search service previously where I created an indexer directly on a SQL DB in the Azure Portal.
Now I have a use-case where I would want to ingest from multiple data sources each having different data schema. Assume these data sources to be 3 search APIs of X,Y,Z teams. All of them take search term and gives back results in their own schema. I want my Azure Search Service to be proxy for these so that I have one search API that a user can use to get results from multiple sources, ordered correctly.
How should I go about doing it? I assume that I might have to create a common schema and whenever user searches something, I would call these 3 APIs and get results, map them to a common schema and then index this data in common schema into Azure Search index. Finally, call this Azure Search API to give back the results to the caller.
I would appreciate any help! If I can get hold of a better documentation for doing this work, that will be great as well.
Your assumption is correct. You can work with 3 different indexes and fire queries against them, or you can try to combine all of them in the same index. The benefit of the second approach is a better way to implement ordering / paging as all the information will be stored in the same index.
It really depends on what you mean by ordered correctly. Should team X be able to see results from teams Y and Z? The only way you can get ranked results like this is to maintain a single index with a common schema containing data from all teams.
One potential pitfall with this approach is conflicts in the schema. For example if one team requires a field to be of a specific datatype or use a specific analyzer, while another team has different requirements. We do this in our indexes, but with some carefully selected common fields and then dedicated fields prefixed according to our own naming convention to avoid conflicts.
One thing to consider is the need to reset the index. If you need to add, change or remove fields you will have to delete the index and create it again with a new schema. If you have a common index and team X needs to add a new property, you would need to reset (delete and create) the common index which affects all teams.
So, creating separate indexes per team has its benefits. Each team can have their own schema without risk of conflicts and they can reset their index without affecting the other teams.

Complex Finds in Domain Driven Design

I'm looking into converting part of an large existing VB6 system, into .net. I'm trying to use domain driven design, but I'm having a hard time getting my head around some things.
One thing that I'm completely stumped on is how I should handle complex find statements. For example, we currently have a screen that displays a list of saved documents, that the user can select and print off, email, edit or delete. I have a SavedDocument object that does the trick for all the actions, but it only has the properties relevant to it, and I need to display the client name that the document is for and their email address if they have one. I also need to show the policy reference that this document may have come from. The Client and Policy are linked to the SavedDocument but are their own aggregate roots, so are not loaded at the same time the SavedDocuments are.
The user is also allowed to specify several filters to reduce the list down. These to can be from properties that are stored on the SavedDocument or the Client and Policy.
I'm not sure how to handle this from a Domain driven design point of view.
Do I have a function on a repository that takes the filters and returns me a list of SavedDocuments, that I then have to turn into a different object or DTO, and fill with the additional client and policy information? That seem a little slow as I have to load all the details using multiple calls.
Do I have a function on a repository that takes the filters and returns me a list of SavedDocumentsForList objects that contain just the information I want? This seems the quickest but doesn't feel like I'm using DDD.
Do I load everything from their objects and do all the filtering and column selection in a service? This seems the slowest, but also appears to be very domain orientated.
I'm just really confused how to handle these situations, and I've not really seeing any other people asking questions about it, which masks me feel that I'm missing something.
Queries can be handled in a few ways in DDD. Sometimes you can use the domain entities themselves to serve queries. This approach can become cumbersome in scenarios such as yours when queries require projections of multiple aggregates. In this case, it is easier to use objects explicitly designed for the respective queries - effectively DTOs. These DTOs will be read-only and won't have any behavior. This can be referred to as the read-model pattern.

How do I set default values of fields added to existing entities?

I'm adding 4 new checkboxes to an entity and its form. There are already instances of this entity created in production. I need to have these checkboxes defaulted to checked on these existing entity instances. I set the default value of the field but apparently this only gets used when a new instance of the entity is created. Is there an easy way to set these on all the existing instances?
I could use a one-off workflow, but I don't know how many instances of this entity there are and due to auditing requirements I can't access the production environment.
You could create execute some JavaScript on the load of the form. Of course, this wouldn't update all of the values in the database, but it would update it before a user is able to view it. Do you need all the values in the database defaulted, or will java script work?
Edit
Your best options are either an update multiple ( you can increase the number of records an advanced find returns to 250 records per page) and continue to update all records manually, or perform a batch update. See this related SO question.
There's another way, too. You could write a console application that connects to your server (not that hard if you've done it before and don't have to make it general). Then, you simply execute an update on the service fetching all the existing entities and updating them after the change is made.
As #Daryl says, there's probably a way to do that from the GUI too, but real programmers do it the hard way. :)
Of course I'm kidding. I just love to type code, hehe. Never the less - once you start coding, you have full freedom to affect the data any way you need, forever.
You can do this by exporting the records and change the value for the field and then re-import back it.

Capitalization of Custom Entities, Fields in CRM 2011

In migrating to CRM 2011, we're discovering different developers used different capitalization of custom entities and custom fields. This creates a headache for custom programming using the early bound methods. http://msdn.microsoft.com/en-us/library/gg327844.aspx. Is there a way to normalize the entity/field names before (or after) the migration?
As far as I'm aware. The only way to achieve the correct capitalisation you desire is to recreate the entities with the appropriate names.
Before or after the migration is mostly the upgrade of the CRM Server installation and modifying the database schema to reflect the upgrade, while still maintaining the current data and customisation data.
Thats as far as the "Supported" spiel goes.
As for an actual workaround. If your looking to upgrade anyway I'd be tempted to restore your current CRM 4 system to a test domain. Then look at how feasible it is to change the schema names in the actual "untouchable" crm database. I believe there is a MetaDataSchema.Entity table where this is centrally stored so i'd test this to see how usable this is and what impact it has on say the webservice.
So you face a similiar choice that I face on multiple occasions while working with Dynamics CRM. Go with the supported way, or a bit of "Yee-Ha" development. Sorry it's probably not what you want to hear!
Edit:
In regards to what to change I can't say for sure as I haven't got a CRM 4.0 system to hand only a 2011 at this moment in time. However as an example, there will be a MetadataSchema.Entity table in the [OrganisationName_MSCRM] Database. Of which certain columns will jump out. Name, PhysicalName and Logical Name.
Logical name is the one that CRM users which it defaults to lowercase no matter how you enter it.
I believe PhysicalName and Name are the ones you would be looking to change into lower case.
The actual "Name" of the entity, eg logical name is "account" whereas in CRM where it is displayed in a user friendly way is related through a table called MetadataSchema.LocalizedLabel through the foreign key "ObjectId" which in this case would be the "EntityId" field.
This is where I would be looking to do the changes as it shouldn't have an impact on the rest of the data due to the "logicalname" field being the one CRM probably uses.
As far as your generation for strongly types classes goes.
if you use latebound such as
relatedEntity.LogicalName = "new_related_account";
relatedEntity["relatedaccountid"] = entity["accountid"];
then all the properties and logical names need to be lower case. As this will use the "logicalname" property previously identified in the MetadataSchema table.
Howver using SVCUtil I can only assume it looks at the "Name" and "Physical Name" attributes to give a slightly more user friendly coding experience when it generates the file for use in custom applications.
Though if you are looking to use the early bound class generation it shouldn't be a problem as the definition file generated will provide intellisense on the correct capitalisation of attributes and properties, and if you are using late bound like the example previously it's all lower case. So it's more it will just be a bit untidy to look at than completely impractical =)

Resources