Skip to content

Commit 41da3aa

Browse files
committed
WIP
1 parent d377029 commit 41da3aa

4 files changed

Lines changed: 145 additions & 90 deletions

File tree

src/ConversionExtensions.cs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using Microsoft.Xrm.Sdk;
2+
using Microsoft.Xrm.Sdk.Extensions;
3+
using Microsoft.Xrm.Sdk.Data.Mappings;
4+
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Linq;
8+
using Microsoft.Xrm.Sdk.Query;
9+
using Microsoft.Xrm.Sdk.Data.Extensions;
10+
using Microsoft.Xrm.Sdk.Messages;
11+
12+
namespace LoopbackDataProvider
13+
{
14+
static class ConversionExtensions
15+
{
16+
public static QueryExpression ConvertSchema(QueryExpression queryExpression, QueryMapFactory queryMapFactory)
17+
{
18+
var queryMap = queryMapFactory.Create(queryExpression);
19+
var retval = queryExpression.ConvertSchema(queryMap);
20+
return retval;
21+
}
22+
23+
public static ColumnSet ConvertSchema(ColumnSet columnSet, EntityMap entityMap)
24+
=> new(columnSet.Columns.Select(entityMap.MapAttributeNameExternal).ToArray());
25+
26+
public static EntityReference ConvertSchema(EntityReference entityReference, EntityMap entityMap)
27+
=> new()
28+
{
29+
LogicalName = entityMap.NameMap.ExternalName,
30+
Id = entityReference.Id,
31+
KeyAttributes = ConvertSchema(entityReference.KeyAttributes, entityMap),
32+
33+
Name = entityReference.Name,
34+
ExtensionData = entityReference.ExtensionData,
35+
RowVersion = entityReference.RowVersion,
36+
};
37+
38+
public static KeyAttributeCollection ConvertSchema(KeyAttributeCollection keyAttributeCollection, EntityMap entityMap)
39+
{
40+
var result = new KeyAttributeCollection();
41+
result.AddRange(keyAttributeCollection
42+
.Select(attr => new KeyValuePair<string, object>(
43+
entityMap.MapAttributeNameExternal(attr.Key), attr.Value)
44+
));
45+
return result;
46+
}
47+
48+
public static EntityCollection ConvertSchema(EntityCollection externalEntites, QueryMap queryMap)
49+
{
50+
var mappedEntities = new EntityCollection()
51+
{
52+
EntityName = queryMap.PrimaryEntityMap.NameMap.XrmName,
53+
};
54+
mappedEntities.MoreRecords = externalEntites.MoreRecords;
55+
mappedEntities.MinActiveRowVersion = externalEntites.MinActiveRowVersion;
56+
mappedEntities.TotalRecordCountLimitExceeded = externalEntites.TotalRecordCountLimitExceeded;
57+
mappedEntities.TotalRecordCount = externalEntites.TotalRecordCount;
58+
mappedEntities.PagingCookie = externalEntites.PagingCookie;
59+
mappedEntities.Entities.AddRange(externalEntites.Entities.Select(x => ConvertSchema(x, queryMap)));
60+
61+
return mappedEntities;
62+
}
63+
64+
public static Entity ConvertSchema(Entity externalEntity, QueryMap queryMap)
65+
{
66+
// TODO: Link entities
67+
return ConvertSchema(externalEntity, queryMap.PrimaryEntityMap);
68+
}
69+
70+
public static Entity ConvertSchema(Entity externalEntity, EntityMap entityMap)
71+
{
72+
Entity convertedEntity = new(entityMap.NameMap.XrmName);
73+
74+
foreach (AttributeMap attribute in entityMap.AttributeMap)
75+
{
76+
if (!externalEntity.Attributes.TryGetValue(attribute.NameMap.ExternalName, out var externalValue))
77+
continue;
78+
79+
// TODO: value conversion?
80+
convertedEntity.Attributes[attribute.NameMap.XrmName] = externalValue;
81+
82+
if (attribute.IsPrimaryAttributeId)
83+
{
84+
convertedEntity.Id = (Guid)externalValue;
85+
}
86+
}
87+
88+
return convertedEntity;
89+
}
90+
}
91+
}

src/LoopbackDataProvider.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
<PrivateAssets>all</PrivateAssets>
2727
</PackageReference>
2828
<PackageReference Include="Microsoft.CrmSdk.Data" Version="9.0.2.34">
29-
<IncludeAssets>compile</IncludeAssets>
3029
<PrivateAssets>all</PrivateAssets>
3130
</PackageReference>
3231
<PackageReference Include="GitVersion.MsBuild" Version="5.6.11">

src/LoopbackDataProviderPlugin.cs

Lines changed: 30 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ namespace LoopbackDataProvider
1616
{
1717
public sealed class LoopbackDataProviderPlugin : IPlugin
1818
{
19+
private const string RelatedEntitiesQuery = "RelatedEntitiesQuery";
20+
private const string Query = "Query";
21+
private const string Target = "Target";
22+
private const string ColumnSet = "ColumnSet";
23+
private const string Entity = "Entity";
24+
private const string BusinessEntityCollection = "BusinessEntityCollection";
25+
1926
public void Execute(IServiceProvider serviceProvider)
2027
{
2128
var context = serviceProvider.Get<IPluginExecutionContext>()
@@ -44,87 +51,60 @@ public void Execute(IServiceProvider serviceProvider)
4451

4552
var targetEntityName = dataSource.Attributes.First(x => x.Value is string).Value.ToString();
4653

47-
48-
var mapping = Mapping.Create(service, context.PrimaryEntityName);
49-
5054
var entityMetadata = service.GetEntityMetadata(context.PrimaryEntityName);
51-
5255
var typeMapFactory = new DefaultTypeMapFactory();
5356

54-
5557
switch (context.MessageName)
5658
{
5759
case "Retrieve":
58-
var entityMap =EntityMapFactory.Create(entityMetadata, typeMapFactory, "mappingEntityAlias");
59-
60-
var target = (EntityReference)context.InputParameters["Target"];
61-
var columnSet = (ColumnSet)context.InputParameters["ColumnSet"];
62-
var relatedEntitiesQuery = (RelationshipQueryCollection)context.InputParameters["RelatedEntitiesQuery"];
60+
var entityMap = EntityMapFactory.Create(entityMetadata, typeMapFactory, entityAlias: null);
61+
62+
var target = (EntityReference)context.InputParameters[Target];
63+
var columnSet = (ColumnSet)context.InputParameters[ColumnSet];
64+
var relatedEntitiesQuery = (RelationshipQueryCollection)context.InputParameters[RelatedEntitiesQuery];
6365
if (relatedEntitiesQuery.Any())
64-
throw new NotImplementedException("RelatedEntitiesQuery");
66+
throw new NotImplementedException(RelatedEntitiesQuery);
6567

66-
var mappedTarget = Mapping.ReplaceEntityLogicalNames(target, context.PrimaryEntityName, entityMetadata.ExternalName);
67-
var mappedColumns = columnSet.Columns.Select(entityMap.MapAttributeNameExternal).ToArray();
68-
69-
var retrieveResponse = (RetrieveResponse)service.Execute(new RetrieveRequest {
70-
71-
ColumnSet = new (mappedColumns),
72-
Target = mappedTarget,
68+
var retrieveResponse = (RetrieveResponse)service.Execute(new RetrieveRequest
69+
{
70+
ColumnSet = ConversionExtensions.ConvertSchema(columnSet, entityMap),
71+
Target = ConversionExtensions.ConvertSchema(target, entityMap),
7372
});
7473

75-
var mappedEntity = retrieveResponse.Entity.ToEntity(entityMap);
76-
context.OutputParameters["Entity"] = mappedEntity;
74+
var mappedEntity = ConversionExtensions.ConvertSchema(retrieveResponse.Entity, entityMap);
75+
context.OutputParameters[Entity] = mappedEntity;
7776
return;
78-
77+
7978
case "RetrieveMultiple":
80-
8179
var queryMapFactory = new QueryMapFactory(service, typeMapFactory);
8280

83-
var query = (QueryExpression)context.InputParameters["Query"];
81+
var query = (QueryExpression)context.InputParameters[Query];
8482
var queryMap = queryMapFactory.Create(query);
85-
83+
84+
foreach (var attr in queryMap.PrimaryEntityMap.AttributeMap)
85+
tracing.Trace($"attr ({attr.IsPrimaryAttributeId}) : {attr.NameMap.ExternalName} -> {attr.NameMap.XrmName}");
86+
8687
var convertedQuery = query.ConvertSchema(queryMap);
8788

8889
tracing.Trace($"{nameof(convertedQuery)}: {convertedQuery.EntityName} ({string.Join(", ", convertedQuery.ColumnSet.Columns)})");
8990
tracing.Trace($"{nameof(convertedQuery)}: Conditions: {convertedQuery.Criteria.Conditions.Count()}");
9091

9192
var retrieveMultipleResponse = service.RetrieveMultiple(convertedQuery);
92-
var mappedEntities = new EntityCollection();
93-
94-
mappedEntities.Entities.AddRange(retrieveMultipleResponse.Entities.Select(x=> x.ToEntity(queryMap.PrimaryEntityMap)));
9593

96-
foreach (var item in mappedEntities.Entities)
97-
{
98-
tracing.Trace($"{item.LogicalName} {item.Id} ({string.Join(",", item.Attributes.Select(a=> $"{a.Key}: {a.Value} ({a.Value?.GetType()?.Name})"))})");
99-
}
94+
var mappedEntities = ConversionExtensions.ConvertSchema(retrieveMultipleResponse, queryMap);
10095

101-
mappedEntities.MoreRecords = retrieveMultipleResponse.MoreRecords;
102-
mappedEntities.MinActiveRowVersion = retrieveMultipleResponse.MinActiveRowVersion;
103-
mappedEntities.TotalRecordCountLimitExceeded = retrieveMultipleResponse.TotalRecordCountLimitExceeded;
104-
mappedEntities.TotalRecordCount = retrieveMultipleResponse.TotalRecordCount;
105-
mappedEntities.PagingCookie = retrieveMultipleResponse.PagingCookie;
96+
foreach (var item in mappedEntities.Entities)
97+
tracing.Trace($"{item.LogicalName} {item.Id} ({string.Join(",", item.Attributes.Select(a => $"{a.Key}: {a.Value} ({a.Value?.GetType()?.Name})"))})");
10698

107-
context.OutputParameters["BusinessEntityCollection"] = mappedEntities;
99+
context.OutputParameters[BusinessEntityCollection] = mappedEntities;
108100
return;
109101

110102
case "Create":
111103
case "Update":
112104
case "Delete":
113105
default:
114-
break;
106+
throw new NotImplementedException($"Message '{context.MessageName}'");
115107
}
116-
117-
var request = new OrganizationRequest(context.MessageName);
118-
119-
request.Parameters.AddRange(
120-
mapping.ConvertSchema(context.InputParameters));
121-
122-
var response = service.Execute(request);
123-
124-
context.OutputParameters.AddRange(
125-
mapping.ConvertSchema(response.Results));
126108
}
127-
128-
129109
}
130110
}

src/Mapping.cs renamed to src/ValueConversion.cs

Lines changed: 24 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -8,62 +8,45 @@
88
using Microsoft.Xrm.Sdk.Query;
99
using Microsoft.Xrm.Sdk.Data.Extensions;
1010
using Microsoft.Xrm.Sdk.Messages;
11-
1211
namespace LoopbackDataProvider
1312
{
14-
sealed class Mapping
13+
/// <summary>
14+
/// WIP
15+
/// </summary>
16+
class ValueConversion
1517
{
16-
internal static Mapping Create(IOrganizationService service, string primaryEntityName)
17-
{
18-
var typeMapFactory = new DefaultTypeMapFactory();
19-
var queryMapFactory = new QueryMapFactory(service, typeMapFactory);
20-
return new(queryMapFactory);
21-
}
22-
23-
readonly QueryMapFactory queryMapFactory;
24-
25-
Mapping(QueryMapFactory queryMapFactory)
26-
{
27-
this.queryMapFactory = queryMapFactory;
28-
}
29-
3018
internal IEnumerable<KeyValuePair<string, object>> ConvertSchema(IEnumerable<KeyValuePair<string, object>> kvps)
3119
=> kvps.Select(ip => new KeyValuePair<string, object>(ip.Key, ConvertSchema(ip.Value)));
3220

21+
3322
object ConvertSchema(object obj)
34-
=> obj switch
35-
{
36-
EntityReference entityReference
37-
=> ConvertSchema(entityReference),
23+
=> obj switch
24+
{
25+
EntityReference entityReference
26+
=> ConvertSchema(entityReference),
3827

39-
Entity entity
40-
=> ConvertSchema(entity),
28+
Entity entity
29+
=> ConvertSchema(entity),
4130

42-
EntityCollection entityCollection
43-
=> ConvertSchema(entityCollection),
31+
EntityCollection entityCollection
32+
=> ConvertSchema(entityCollection),
4433

45-
AttributeCollection attributeCollection
46-
=> ConvertSchema(attributeCollection),
34+
AttributeCollection attributeCollection
35+
=> ConvertSchema(attributeCollection),
4736

48-
QueryExpression queryExpression
49-
=> ConvertSchema(queryExpression),
37+
QueryExpression queryExpression
38+
=> ConvertSchema(queryExpression),
5039

51-
_ => obj,
52-
};
40+
_ => obj,
41+
};
5342

5443
EntityCollection ConvertSchema(EntityCollection entityCollection)
5544
{
5645
throw new NotImplementedException();
5746
//var retval = queryExpression.ConvertSchema(queryMap);
58-
// return retval;
47+
// return retval;
5948
}
6049

61-
QueryExpression ConvertSchema(QueryExpression queryExpression)
62-
{
63-
var queryMap = queryMapFactory.Create(queryExpression);
64-
var retval = queryExpression.ConvertSchema(queryMap);
65-
return retval;
66-
}
6750

6851
object ConvertSchema(object obj, string logicalName, string newLogicalName)
6952
=> obj switch
@@ -111,6 +94,8 @@ static QueryExpression ReplaceEntityLogicalName(QueryExpression queryExpression,
11194
}
11295

11396

97+
98+
11499
public static EntityReference ReplaceEntityLogicalNames(EntityReference entityReference, string logicalName, string newLogicalName)
115100
=> new()
116101
{
@@ -156,8 +141,8 @@ static AttributeCollection ReplaceEntityLogicalNames(AttributeCollection attribu
156141
{
157142
throw new NotImplementedException();
158143
var retval = new AttributeCollection();
159-
// retval.AddRange(
160-
// ReplaceEntityLogicalNames(attributeCollection.AsEnumerable(), logicalName, newLogicalName));
144+
// retval.AddRange(
145+
// ReplaceEntityLogicalNames(attributeCollection.AsEnumerable(), logicalName, newLogicalName));
161146
return retval;
162147
}
163148

0 commit comments

Comments
 (0)