[英]How can I get IEdmEntityTypeReference.Key() to return keys in the correct order?
我正在使用 OData,我不太熟悉。 当 OData 将实体附加到DataServiceContext class 中的上下文时,他们使用 ODataResourceMetadataBuilder 设置.Identity
属性。
ODataResourceMetadataBuilder entityMetadataBuilder = this.GetEntityMetadataBuilderInternal(descriptor);
descriptor.EditLink = entityMetadataBuilder.GetEditLink();
descriptor.Identity = entityMetadataBuilder.GetId();
这经历了一系列从ConventionalODataEntityMetadataBuilder.GetId()开始的 OData 类,最终到达在 OData 的DataServiceUrlKeyDelimiter中创建 CompositeKey 的位置
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);
}
键是在我的 class 中使用键注释定义的
public class MyClass
{
[Key, Column(Order = 0)]
public Guid CompositeKeyB { get; set; }
[Key, Column(Order = 1)]
public Guid CompositeKeyA { get; set; }
}
请注意,这些键按字母顺序向后排列。
当上面的代码运行以设置.Identity
字段时,它按字母顺序给我键,而不是按我在数据注释中指定的顺序。
这是一个问题,因为当检索实体时,键的顺序正确,因此它具有不同的.Identity
属性,并且被视为与附加实例不同的单独实例。 这意味着它不会使用新数据更新附加实体,并且实体的第二个副本会在上下文中创建。
有没有一种简单的方法来纠正这个问题,还是我坚持编写自己的代码来使用反射以正确的顺序获取键? 我目前看不到在从IEdmEntityTypeReference.Key()
返回的IEdmStructuralProperty
属性中查找 Order 值的方法。
之所以出现此问题,是因为在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);
}
}
我们使用的解决方案是随后将原始排序应用于复合键属性,尽管潜在的解决方案也可能是从 foreach 循环中删除.OrderBy(p => p.Name)
。 不过,我不确定这是否会导致其他问题,因此之后为复合键重新应用键排序顺序似乎是最安全的。
if (loadedKeyProperties.Count > 1)
{
var orderedKeyPropertyNames = keyProperties.Select(k => k.Name).ToList();
loadedKeyProperties = loadedKeyProperties.OrderBy(k => orderedKeyPropertyNames.IndexOf(k.Name)).ToList();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.