The xConnect model
The xConnect model is a representation of the structure and type of data that is collected by xConnect. The xConnect model defines:
-
Contact and interaction facets, such as
PersonalInformation
andIpInfo
-
Event types, such a
Goal
andOutcome
-
All CLR types, such as
System.String
or custom classes used by facets and events
The xConnect model is made up of smaller partial models. The xConnect service is aware of the entire model. Clients, such as a CRM system, only need to be aware of the partial model that it is going to use. It is not possible to use a model that has not been deployed to xConnect.
The xConnect model is defined in code
The xConnect model is defined in code and can be spread across multiple DLLs. For example, Sitecore’s default facets and events are stored in the Sitecore.XConnect.Collection.Model
DLL, whereas the facets required by the Experience Optimization feature are stored in the Sitecore.ContentTesting.Model.xConnect.Models
DLL.
For more information about creating a model, see:
xConnect hosts a JSON version of all partial models
Within xConnect, the \App_data\Models
folder must contain a JSON representation of all models. When a new model is created, it must be deployed to xConnect before it can be used. The xConnect version of the model is considered to be the authoritative version. All client-side models are validated against the xConnect version when the xConnect Client API is initialized. The following properties of the client’s model must match the xConnect model:
-
Model name
-
Model version
-
Facets, events, and types
Clients reference the models that they require
Clients should have a copy of the model DLLs that they are going to use. In the following example, the CRM server is only aware of the Documentation.Model model. The Content Delivery server is aware of the the Documentation.Model and default Sitecore models.
Sitecore core roles such as Content Management and Content Delivery build a run-time model from a configured list of models. If you use the xConnect Client API in a non-Sitecore context, you must instantiate the client with the model that you require. For more information, see:
Type restrictions
The following restrictions apply to all types used in the model, including the property types of facets and events:
-
Only object and enum types can be registered using
.RegisterType<T>
- you cannot add aList<string>
-
All types must have a parameterless constructor - the constructor does not have to be public
-
Use concrete type
List<T>
for collections -
Use concrete type
Dictionary<K,V>
for dictionaries -
Types must be unique across referenced schemas - this is not normally an issue unless you are manually registering types with
.RegisterType<T>
-
Properties can be nullable - e.g.
public?intLoyaltyNumber
.
The model builder always registers core types such as Facet
and Event
. This includes all built-in types that inherit Event
, such as Goal
and Outcome
.
If you set a List<T>
property on a facet or custom event to null, that list property will be empty instead of null when it is read again. oData does not support null values in this context, even though the value is null in the collection database. However, the Interactions
property on the Contact
will return null if no RelatedInteractionExpandOptions
are specified. In an oData context, contacts and interactions are related entities.
Personally identifiable information (PII)
The xConnect model includes out-of-the-box fields that might include personally identifiable information (PII). Here's a list of facets where at least one field is marked as PIISensitive
:
PersonalInformation
Birthdate { get; set; }
FirstName { get; set; }
MiddleName { get; set; }
LastName { get; set; }
Nickname { get; set; }
Avatar
Picture { get; set; }
Address (Record from AddressList facet)
AddressLine1 { get; set; }
AddressLine2 { get; set; }
AddressLine3 { get; set; }
AddressLine4 { get; set; }
GeoCoordinate { get; set; }
PhoneNumber (Record from PhoneNumberList facet)
Extension { get; set; }
Number { get; set; }
AreaCode { get; set; }
EmailAddress (Record from EmailAddressList facet)
SmtpAddress { get; set; }Birthdate { get; set; }
FirstName { get; set; }
MiddleName { get; set; }
LastName { get; set; }
Nickname { get; set; }
Naming conventions
The following naming conventions apply to type names, property names, enumerations, facet keys, and model names:
-
Must start with a lowercase or capital English letter
-
First letter can be followed by any combination of upper or lowercase English letters, numbers or underscores
Model names and namespaces can contain multiple identifiers separated by dot. For example: My.Name_Space0 or My.Model_Name1.
Facet and event uniqueness
Facets and events must be unique within a model and across referenced models. Facet uniqueness is determined by a combination of the following:
-
Facet type
-
Facet key
-
Facet entity (either
Contact
orInteraction
)
You can define a facet with the same type and key for contacts and for interactions:
modelBuilder.DefineFacet<Contact, FacetType>("FacetKey");
modelBuilder.DefineFacet<Interaction, FacetType>("FacetKey");
Events are defined by a type. If two models share an event type, the models cannot be used together unless the event type is specified in a separate, shared model. In the following example, Documentation.Model.dll and Testing.Model.dll both define an event named RegisterEvent:
In order to use Documentation.Model.dll and Testing.Model.dll together, the shared event type must be moved to a separate model that is referenced by Documentation.Model.dll and Testing.Model.dll:
Model name uniqueness across referenced models
Model names must be unique across all referenced models, including second order references. For example:
-
A model named CRM.Model cannot reference another model named CRM.Model
-
A model named CRM.Model cannot reference Documentation.Model which in turn references another model named CRM.Model
A DuplicateModelNameException
exception is thrown if model names are not unique. The following example results in a DuplicateModelNameException
:
var model1 = new XdbModel("Test", new XdbModelVersion(0, 1), new XdbNamedType[0], new XdbFacetDefinition[0], new XdbModel[0]);
var model2 = new XdbModel("Test", new XdbModelVersion(0, 1), new XdbNamedType[0], new XdbFacetDefinition[0], new XdbModel[0]);
var model3Builder = new XdbModelBuilder("Composite", new XdbModelVersion(0, 1));
model3Builder.ReferenceModel(model2);
model3Builder.BuildModel(); // This will work, since only one model named "Test"
model3Builder.ReferenceModel(model1);
model3Builder.BuildModel(); // This will fail, as there is already a model named "Test"