Как я могу получить IEdmEntityTypeReference.Key () для возврата ключей в правильном порядке? - PullRequest
0 голосов
/ 15 апреля 2020

Я работаю с OData, с чем я не слишком знаком. Когда OData присоединяет сущность к контексту в классе DataServiceContext , они устанавливают свойство .Identity с использованием ODataResourceMetadataBuilder.

ODataResourceMetadataBuilder entityMetadataBuilder = this.GetEntityMetadataBuilderInternal(descriptor);

descriptor.EditLink = entityMetadataBuilder.GetEditLink();
descriptor.Identity = entityMetadataBuilder.GetId();

Это проходит через серию классов OData, начинающихся с ConventionalODataEntityMetadataBuilder.GetId () , который в конечном итоге попадает туда, где создается CompositeKey в OData DataServiceUrlKeyDelimiter

internal void AppendKeyExpression(IEdmStructuredValue entity, StringBuilder builder)
{
    Debug.Assert(entity != null, "entity != null");
    Debug.Assert(builder != null, "builder != null");

    IEdmEntityTypeReference edmEntityTypeReference = entity.Type as IEdmEntityTypeReference;
    if (edmEntityTypeReference == null || !edmEntityTypeReference.Key().Any())
    {
        throw Error.Argument(ErrorStrings.Content_EntityWithoutKey, "entity");
    }

    // Problem occurs here - edmEntityTypeReference.Key() has the keys in the wrong order.
    this.AppendKeyExpression(edmEntityTypeReference.Key().ToList(), p => p.Name, p => GetPropertyValue(entity.FindPropertyValue(p.Name), entity.Type), builder);
}

Ключи определены в моем классе с помощью аннотаций ключей

public class MyClass
{
    [Key, Column(Order = 0)]
    public Guid CompositeKeyB { get; set; }

    [Key, Column(Order = 1)]
    public Guid CompositeKeyA { get; set; }
}

Обратите внимание, что клавиши расположены в алфавитном порядке назад.

Когда приведенный выше код запускается для установки поля .Identity, он дает мне ключи в алфавитном порядке, а не в порядке, указанном в аннотации данных.

Это проблема, потому что когда объект извлекается, ключи располагаются в правильном порядке, поэтому у него есть свойство .Identity, и он рассматривается как отдельный экземпляр, чем прикрепленный экземпляр. Это означает, что он не обновляет присоединенную сущность новыми данными, а также что вторая копия сущности создается в контексте.

Есть ли простой способ исправить это, или я застрял с написанием собственного кода, чтобы получить ключи в правильном порядке с помощью отражения? В настоящее время я не вижу способа найти значение Order в свойстве IEdmStructuralProperty, которое возвращается из IEdmEntityTypeReference.Key().

1 Ответ

1 голос
/ 16 апреля 2020

Проблема возникла из-за того, что в методе ClientEdmModel.GetOrCreateEdmTypeInternal она упорядочивает свойства по имени, а затем сортирует их по ключевым и неключевым свойствам.

// Problem is the .OrderBy in this line of code
foreach (PropertyInfo property in ClientTypeUtil.GetPropertiesOnType(type, /*declaredOnly*/edmBaseType != null).OrderBy(p => p.Name))
{
    IEdmProperty edmProperty = this.CreateEdmProperty((EdmStructuredType)entityType, property);
    loadedProperties.Add(edmProperty);

    if (edmBaseType == null && keyProperties.Any(k => k.DeclaringType == type && k.Name == property.Name))
    {
        Debug.Assert(edmProperty.PropertyKind == EdmPropertyKind.Structural, "edmProperty.PropertyKind == EdmPropertyKind.Structural");
        Debug.Assert(edmProperty.Type.TypeKind() == EdmTypeKind.Primitive || edmProperty.Type.TypeKind() == EdmTypeKind.Enum, "edmProperty.Type.TypeKind() == EdmTypeKind.Primitive || edmProperty.Type.TypeKind() == EdmTypeKind.Enum");
        loadedKeyProperties.Add((IEdmStructuralProperty)edmProperty);
    }
}

Решение, которое мы использовали, заключалось в применении оригинала сортировка по составным ключевым свойствам впоследствии, хотя потенциальное решение может также заключаться в удалении .OrderBy(p => p.Name) из foreach l oop. Однако я не уверен, что это вызовет другие проблемы, поэтому представляется наиболее безопасным просто повторно применить порядок сортировки ключей для составных ключей.

if (loadedKeyProperties.Count > 1)
{
    var orderedKeyPropertyNames = keyProperties.Select(k => k.Name).ToList();
    loadedKeyProperties = loadedKeyProperties.OrderBy(k => orderedKeyPropertyNames.IndexOf(k.Name)).ToList();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...