Skip to content

Commit

Permalink
Revisits and resolves a bunch of edge cases for Create, Upsert and Cr…
Browse files Browse the repository at this point in the history
…eateMultiple and UpsertMultiple with alternate keys DynamicsValue/fake-xrm-easy#172
  • Loading branch information
jordimontana82 committed Jan 12, 2025
1 parent 57ccf1c commit 8de9b55
Show file tree
Hide file tree
Showing 17 changed files with 695 additions and 251 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

### Changed

- Resolves many issues in Create, Upsert, and CreateMultiple and UpsertMultiple when alternate keys were used - https://github.com/DynamicsValue/fake-xrm-easy/issues/172
- TracingService will also output to the default standard output - https://github.com/DynamicsValue/fake-xrm-easy/issues/163
- **BREAKING CHANGE**: This will **only** affect you if you use XrmRealContext class. Moved XrmRealContext to a separate FakeXrmEasy.Integration package to remove dependency on XrmTooling - https://github.com/DynamicsValue/fake-xrm-easy/issues/160
- Resolves an issue in FetchXml queries when using arithmetic values and no early bound assemblies are used. It will now read from injected metadata in absence of proxy type assemblies - https://github.com/DynamicsValue/fake-xrm-easy/issues/158
- Resolves issue in MetadataGenerator where relationship properties were generated in the wrong order, also generates ManyToMany relationship properties - https://github.com/DynamicsValue/fake-xrm-easy/issues/135
Expand Down
49 changes: 49 additions & 0 deletions src/FakeXrmEasy.Core/Db/InMemoryTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using Microsoft.Xrm.Sdk.Metadata;
using System;
using System.Collections.Generic;
using System.Linq;
using FakeXrmEasy.Abstractions;

namespace FakeXrmEasy.Core.Db
{
Expand Down Expand Up @@ -107,6 +109,51 @@ protected internal Entity GetById(Guid key)
return _rows[key];
}

/// <summary>
/// Checks if there is a matching record that matches the alternate key provided.
/// </summary>
/// <param name="key">The metadata of the Alternate Key</param>

Check warning on line 115 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_365)

XML comment has a param tag for 'key', but there is no parameter by that name

Check warning on line 115 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_365)

XML comment has a param tag for 'key', but there is no parameter by that name

Check warning on line 115 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_2016)

XML comment has a param tag for 'key', but there is no parameter by that name

Check warning on line 115 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_2015)

XML comment has a param tag for 'key', but there is no parameter by that name

Check warning on line 115 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_9)

XML comment has a param tag for 'key', but there is no parameter by that name
/// <param name="key">The key values</param>

Check warning on line 116 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_365)

XML comment has a param tag for 'key', but there is no parameter by that name

Check warning on line 116 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_365)

XML comment has a param tag for 'key', but there is no parameter by that name

Check warning on line 116 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_2016)

XML comment has a param tag for 'key', but there is no parameter by that name

Check warning on line 116 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_2015)

XML comment has a param tag for 'key', but there is no parameter by that name

Check warning on line 116 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_9)

XML comment has a param tag for 'key', but there is no parameter by that name
/// <returns></returns>
protected internal Entity GetByKeyAttributeCollection(KeyAttributeCollection keyAttributeValues)

Check failure on line 118 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY)

The type or namespace name 'KeyAttributeCollection' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 118 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY)

The type or namespace name 'KeyAttributeCollection' could not be found (are you missing a using directive or an assembly reference?)

Check warning on line 118 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_365)

Parameter 'keyAttributeValues' has no matching param tag in the XML comment for 'InMemoryTable.GetByKeyAttributeCollection(KeyAttributeCollection)' (but other parameters do)

Check warning on line 118 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_365)

Parameter 'keyAttributeValues' has no matching param tag in the XML comment for 'InMemoryTable.GetByKeyAttributeCollection(KeyAttributeCollection)' (but other parameters do)

Check warning on line 118 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_2016)

Parameter 'keyAttributeValues' has no matching param tag in the XML comment for 'InMemoryTable.GetByKeyAttributeCollection(KeyAttributeCollection)' (but other parameters do)

Check warning on line 118 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_2015)

Parameter 'keyAttributeValues' has no matching param tag in the XML comment for 'InMemoryTable.GetByKeyAttributeCollection(KeyAttributeCollection)' (but other parameters do)

Check failure on line 118 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_2013)

The type or namespace name 'KeyAttributeCollection' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 118 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_2013)

The type or namespace name 'KeyAttributeCollection' could not be found (are you missing a using directive or an assembly reference?)

Check warning on line 118 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_9)

Parameter 'keyAttributeValues' has no matching param tag in the XML comment for 'InMemoryTable.GetByKeyAttributeCollection(KeyAttributeCollection)' (but other parameters do)
{
return Rows.FirstOrDefault(row => keyAttributeValues.All(k => row.Attributes.ContainsKey(k.Key) && row.Attributes[k.Key] != null && row.Attributes[k.Key].Equals(k.Value)));
}


/// <summary>
/// Checks if the record exists using any of the alternate keys currently present in metadata, and if so, returns the matched key metadata
/// </summary>
/// <param name="record">The record whose attribute values will be used for searching</param>
/// <returns>The record that matches one of the entity key metadata, null if none found otherwise</returns>
protected internal Entity GetByAlternateKeys(Entity record, out EntityKeyMetadata matchedKeyMetadata)

Check failure on line 129 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY)

The type or namespace name 'EntityKeyMetadata' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 129 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY)

The type or namespace name 'EntityKeyMetadata' could not be found (are you missing a using directive or an assembly reference?)

Check warning on line 129 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_365)

Parameter 'matchedKeyMetadata' has no matching param tag in the XML comment for 'InMemoryTable.GetByAlternateKeys(Entity, out EntityKeyMetadata)' (but other parameters do)

Check warning on line 129 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_365)

Parameter 'matchedKeyMetadata' has no matching param tag in the XML comment for 'InMemoryTable.GetByAlternateKeys(Entity, out EntityKeyMetadata)' (but other parameters do)

Check warning on line 129 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_2016)

Parameter 'matchedKeyMetadata' has no matching param tag in the XML comment for 'InMemoryTable.GetByAlternateKeys(Entity, out EntityKeyMetadata)' (but other parameters do)

Check warning on line 129 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_2015)

Parameter 'matchedKeyMetadata' has no matching param tag in the XML comment for 'InMemoryTable.GetByAlternateKeys(Entity, out EntityKeyMetadata)' (but other parameters do)

Check failure on line 129 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_2013)

The type or namespace name 'EntityKeyMetadata' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 129 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_2013)

The type or namespace name 'EntityKeyMetadata' could not be found (are you missing a using directive or an assembly reference?)

Check warning on line 129 in src/FakeXrmEasy.Core/Db/InMemoryTable.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_9)

Parameter 'matchedKeyMetadata' has no matching param tag in the XML comment for 'InMemoryTable.GetByAlternateKeys(Entity, out EntityKeyMetadata)' (but other parameters do)
{
matchedKeyMetadata = null;
var entityMetadata = _metadata._entityMetadata;

var keyMetadata = entityMetadata?.Keys;
if (keyMetadata == null)
{
return null;
}

foreach (var key in keyMetadata)
{
var keyAttributes = record.ToAlternateKeyAttributeCollection(key);
if (keyAttributes != null)
{
var matchedRecord = GetByKeyAttributeCollection(keyAttributes);
if (matchedRecord != null)
{
matchedKeyMetadata = key;
return matchedRecord.Clone();
}
}
}

return null;
}

/// <summary>
/// Returns an IEnumerable of all rows in the current table
/// </summary>
Expand Down Expand Up @@ -135,5 +182,7 @@ protected internal EntityMetadata GetEntityMetadata()
{
return _metadata._entityMetadata;
}


}
}
23 changes: 23 additions & 0 deletions src/FakeXrmEasy.Core/Extensions/EntityExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -678,5 +678,28 @@ public static EntityReference ToEntityReferenceWithKeyAttributes(this Entity e)
#endif
return result;
}

/// <summary>
/// Checks if there is a combination of attributes that matches the specified key, and so, it returns it. Returns null otherwise
/// </summary>
/// <param name="e">The entity record that might have key values that match the key</param>
/// <param name="key">The entity key metadata to be used for matching</param>
/// <returns></returns>
public static KeyAttributeCollection ToAlternateKeyAttributeCollection(this Entity e, EntityKeyMetadata key)

Check failure on line 688 in src/FakeXrmEasy.Core/Extensions/EntityExtensions.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY)

The type or namespace name 'EntityKeyMetadata' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 688 in src/FakeXrmEasy.Core/Extensions/EntityExtensions.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY)

The type or namespace name 'KeyAttributeCollection' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 688 in src/FakeXrmEasy.Core/Extensions/EntityExtensions.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY)

The type or namespace name 'EntityKeyMetadata' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 688 in src/FakeXrmEasy.Core/Extensions/EntityExtensions.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY)

The type or namespace name 'KeyAttributeCollection' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 688 in src/FakeXrmEasy.Core/Extensions/EntityExtensions.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_2013)

The type or namespace name 'EntityKeyMetadata' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 688 in src/FakeXrmEasy.Core/Extensions/EntityExtensions.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_2013)

The type or namespace name 'KeyAttributeCollection' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 688 in src/FakeXrmEasy.Core/Extensions/EntityExtensions.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_2013)

The type or namespace name 'EntityKeyMetadata' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 688 in src/FakeXrmEasy.Core/Extensions/EntityExtensions.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_2013)

The type or namespace name 'KeyAttributeCollection' could not be found (are you missing a using directive or an assembly reference?)
{
if (key.KeyAttributes.All(k => e.Attributes.ContainsKey(k)))
{
var keyAttributeValues = new KeyAttributeCollection();
foreach (var k in key.KeyAttributes)
{
keyAttributeValues.Add(k, e[k]);
}
return keyAttributeValues;
}

return null;
}


}
}
26 changes: 26 additions & 0 deletions src/FakeXrmEasy.Core/Extensions/EntityKeyMetadataExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using Microsoft.Xrm.Sdk.Metadata;

namespace FakeXrmEasy.Core.Extensions
{
/// <summary>
/// Extension methods for EntityKeyMetadata
/// </summary>
public static class EntityKeyMetadataExtensions
{
/// <summary>
/// Returns the user localized label of the key if one was set in metadata, or the list of columns that are part of the key otherwise
/// </summary>
/// <param name="keyMetadata"></param>
/// <returns></returns>
public static string GetDisplayName(this EntityKeyMetadata keyMetadata)

Check failure on line 15 in src/FakeXrmEasy.Core/Extensions/EntityKeyMetadataExtensions.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY)

The type or namespace name 'EntityKeyMetadata' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 15 in src/FakeXrmEasy.Core/Extensions/EntityKeyMetadataExtensions.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY)

The type or namespace name 'EntityKeyMetadata' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 15 in src/FakeXrmEasy.Core/Extensions/EntityKeyMetadataExtensions.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_2013)

The type or namespace name 'EntityKeyMetadata' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 15 in src/FakeXrmEasy.Core/Extensions/EntityKeyMetadataExtensions.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_2013)

The type or namespace name 'EntityKeyMetadata' could not be found (are you missing a using directive or an assembly reference?)
{
var label = keyMetadata.DisplayName?.UserLocalizedLabel?.Label;
if (!string.IsNullOrWhiteSpace(label))
{
return label;
}

return string.Join(",", keyMetadata.KeyAttributes);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FakeXrmEasy.Extensions;

namespace FakeXrmEasy.Middleware.Crud.FakeMessageExecutors
{
Expand Down Expand Up @@ -44,16 +45,17 @@ public OrganizationResponse Execute(OrganizationRequest request, IXrmFakedContex
foreach (var record in records)
{
UpsertResponse response = null;
if (ctx.ContainsEntity(record.LogicalName, record.Id))
var entityId = ctx.GetRecordUniqueId(record.ToEntityReferenceWithKeyAttributes(), validate: false);
if (ctx.ContainsEntity(record.LogicalName, entityId))
{
ctx.UpdateEntity(record);
response = new UpsertResponse();
response.Results.Add("RecordCreated", false);
response.Results.Add("Target", new EntityReference(record.LogicalName, record.Id));
response.Results.Add("Target", new EntityReference(record.LogicalName, entityId));
}
else
{
var id = ctx.CreateEntity(record);
var id = ctx.CreateEntity(record, isUpsert: true);
response = new UpsertResponse();
response.Results.Add("RecordCreated", true);
response.Results.Add("Target", new EntityReference(record.LogicalName, id));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public OrganizationResponse Execute(OrganizationRequest request, IXrmFakedContex
else
{
recordCreated = true;
entityId = service.Create(upsertRequest.Target);
entityId = ctx.CreateEntity(upsertRequest.Target, isUpsert: true);
}

var result = new UpsertResponse();
Expand Down
123 changes: 123 additions & 0 deletions src/FakeXrmEasy.Core/XrmFakedContext.Create.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
using System;
using FakeXrmEasy.Abstractions;
using FakeXrmEasy.Core.Extensions;
using FakeXrmEasy.Extensions;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Metadata;

namespace FakeXrmEasy
{
public partial class XrmFakedContext : IXrmFakedContext
{
private void ValidateEntityForCreate(Entity e, bool isUpsert)
{
ValidateEntity(e);
ValidateAlternateKeysForCreate(e, isUpsert);
}

private void ValidateAlternateKeysForCreate(Entity e, bool isUpsert)
{
//1 check if entity metadata has any keys
//2 for each key, check if there are matching attribute values
//3 throw exception if there is any match
if (!Db.ContainsTableMetadata(e.LogicalName) || !Db.ContainsTable(e.LogicalName))
{
return;
}

var table = Db.GetTable(e.LogicalName);


//Check the keyCollection present in the actual entity record key attributes (not necessarily the ones in metadata)
if (!isUpsert && e.KeyAttributes.Count > 0)
{
var matchedRecord = table.GetByKeyAttributeCollection(e.KeyAttributes);
if (matchedRecord != null)
{
throw FakeOrganizationServiceFaultFactory.New(ErrorCodes.DuplicateRecord,
$"Cannot insert duplicate key");
}
else
{
throw FakeOrganizationServiceFaultFactory.New(ErrorCodes.RecordNotFoundByEntityKey,
$"A record with the specified key values does not exist in {e.LogicalName} entity");

}
}

EntityKeyMetadata matchedKeyMetadata;
var existingRecord = table.GetByAlternateKeys(e, out matchedKeyMetadata);
if (existingRecord != null)
{
var keyLabel = matchedKeyMetadata.GetDisplayName();
throw FakeOrganizationServiceFaultFactory.New(ErrorCodes.DuplicateRecordEntityKey,
$"A record that has the attribute values {keyLabel} already exists. The entity key {keyLabel} Key requires that this set of attributes contains unique values. Select unique values and try again.");
}
}

/// <summary>
/// Creates a new entity record
/// </summary>
/// <param name="e"></param>
/// <returns></returns>
/// <exception cref="InvalidOperationException"></exception>
public Guid CreateEntity(Entity e, bool isUpsert = false)

Check warning on line 65 in src/FakeXrmEasy.Core/XrmFakedContext.Create.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_365)

Parameter 'isUpsert' has no matching param tag in the XML comment for 'XrmFakedContext.CreateEntity(Entity, bool)' (but other parameters do)

Check warning on line 65 in src/FakeXrmEasy.Core/XrmFakedContext.Create.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_2016)

Parameter 'isUpsert' has no matching param tag in the XML comment for 'XrmFakedContext.CreateEntity(Entity, bool)' (but other parameters do)

Check warning on line 65 in src/FakeXrmEasy.Core/XrmFakedContext.Create.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_2015)

Parameter 'isUpsert' has no matching param tag in the XML comment for 'XrmFakedContext.CreateEntity(Entity, bool)' (but other parameters do)

Check warning on line 65 in src/FakeXrmEasy.Core/XrmFakedContext.Create.cs

View workflow job for this annotation

GitHub Actions / build-windows (FAKE_XRM_EASY_9)

Parameter 'isUpsert' has no matching param tag in the XML comment for 'XrmFakedContext.CreateEntity(Entity, bool)' (but other parameters do)
{
ValidateEntityForCreate(e, isUpsert);

var clone = e.Clone(e.GetType());

if (clone.Id == Guid.Empty)
{
clone.Id = Guid.NewGuid(); // Add default guid if none present
}

// Hack for Dynamic Entities where the Id property doesn't populate the "entitynameid" primary key
var primaryKeyAttribute = $"{e.LogicalName}id";
if (!clone.Attributes.ContainsKey(primaryKeyAttribute))
{
clone[primaryKeyAttribute] = clone.Id;
}

// Create specific validations
if (clone.Id != Guid.Empty && ContainsEntity(clone.LogicalName, clone.Id))
{
throw new InvalidOperationException($"There is already a record of entity {clone.LogicalName} with id {clone.Id}, can't create with this Id.");
}

if(clone.Attributes.ContainsKey("statecode"))
{
clone["statecode"] = new OptionSetValue(0); //Always active by default regardless of value on Create
}

AddEntityWithDefaults(clone, false);

if (clone.RelatedEntities.Count > 0)
{
foreach (var relationshipSet in clone.RelatedEntities)
{
var relationship = relationshipSet.Key;

var entityReferenceCollection = new EntityReferenceCollection();

foreach (var relatedEntity in relationshipSet.Value.Entities)
{
var relatedId = CreateEntity(relatedEntity);
entityReferenceCollection.Add(new EntityReference(relatedEntity.LogicalName, relatedId));
}

var request = new AssociateRequest
{
Target = clone.ToEntityReference(),
Relationship = relationship,
RelatedEntities = entityReferenceCollection
};
_service.Execute(request);
}
}

return clone.Id;
}
}
}
Loading

0 comments on commit 8de9b55

Please sign in to comment.