diff --git a/src/Microsoft.OData.Edm/Csdl/Parsing/Ast/CsdlPropertyReference.cs b/src/Microsoft.OData.Edm/Csdl/Parsing/Ast/CsdlPropertyReference.cs index 23fa24dca9..faa23393ba 100644 --- a/src/Microsoft.OData.Edm/Csdl/Parsing/Ast/CsdlPropertyReference.cs +++ b/src/Microsoft.OData.Edm/Csdl/Parsing/Ast/CsdlPropertyReference.cs @@ -11,17 +11,15 @@ namespace Microsoft.OData.Edm.Csdl.Parsing.Ast /// internal class CsdlPropertyReference : CsdlElement { - private readonly string propertyName; - - public CsdlPropertyReference(string propertyName, CsdlLocation location) + public CsdlPropertyReference(string propertyName, string propertyAlias, CsdlLocation location) : base(location) { - this.propertyName = propertyName; + PropertyName = propertyName; + PropertyAlias = propertyAlias; } - public string PropertyName - { - get { return this.propertyName; } - } + public string PropertyName { get; } + + public string PropertyAlias { get; } } } diff --git a/src/Microsoft.OData.Edm/Csdl/Parsing/CsdlDocumentParser.cs b/src/Microsoft.OData.Edm/Csdl/Parsing/CsdlDocumentParser.cs index d52d0d9a7f..2b09018daf 100644 --- a/src/Microsoft.OData.Edm/Csdl/Parsing/CsdlDocumentParser.cs +++ b/src/Microsoft.OData.Edm/Csdl/Parsing/CsdlDocumentParser.cs @@ -364,7 +364,7 @@ private static CsdlKey OnEntityKeyElement(XmlElementInfo element, XmlElementValu private CsdlPropertyReference OnPropertyRefElement(XmlElementInfo element, XmlElementValueCollection childValues) { - return new CsdlPropertyReference(Required(CsdlConstants.Attribute_Name), element.Location); + return new CsdlPropertyReference(Required(CsdlConstants.Attribute_Name), Optional(CsdlConstants.Attribute_Alias), element.Location); } private CsdlEnumType OnEnumTypeElement(XmlElementInfo element, XmlElementValueCollection childValues) diff --git a/src/Microsoft.OData.Edm/Csdl/Parsing/SchemaJsonParser.cs b/src/Microsoft.OData.Edm/Csdl/Parsing/SchemaJsonParser.cs index b9575d8dd9..42c47be17c 100644 --- a/src/Microsoft.OData.Edm/Csdl/Parsing/SchemaJsonParser.cs +++ b/src/Microsoft.OData.Edm/Csdl/Parsing/SchemaJsonParser.cs @@ -653,19 +653,36 @@ internal static CsdlKey ParseCsdlKey(string name, JsonElement keyArray, JsonPars IList properties = keyArray.ParseAsArray(context, (v, p) => { + string alias = null; + string propertyName = null; if (v.ValueKind == JsonValueKind.Object) { - // TODO: ODL doesn't support the key referencing a property of a complex type as below. + // Key properties with a key alias are represented as objects with one member + // whose name is the key alias and whose value is a string containing the path to the property. // "$Key": [ // { // "EntityInfoID": "Info/ID" // } // ] - p.ReportError(EdmErrorCode.InvalidKeyValue, "It doesn't support the key object."); + var objectProperties = v.EnumerateObject(); + if (objectProperties.Count() != 1) + { + p.ReportError(EdmErrorCode.InvalidKeyValue, "Key properties with a key alias are represented as objects with only one member."); + } + else + { + var property = objectProperties.First(); + alias = property.Name; + propertyName = property.Value.ParseAsString(context); + } + } + else + { + // Key properties without a key alias are represented as strings containing the property name. + propertyName = v.ParseAsString(context); } - string propertyName = v.ParseAsString(context); - return new CsdlPropertyReference(propertyName, context.Location()); + return new CsdlPropertyReference(propertyName, alias, context.Location()); }); return new CsdlKey(properties, context.Location()); diff --git a/src/Microsoft.OData.Edm/Csdl/Semantics/BadElements/UnresolvedPropertyRef.cs b/src/Microsoft.OData.Edm/Csdl/Semantics/BadElements/UnresolvedPropertyRef.cs new file mode 100644 index 0000000000..d3e9c8906a --- /dev/null +++ b/src/Microsoft.OData.Edm/Csdl/Semantics/BadElements/UnresolvedPropertyRef.cs @@ -0,0 +1,28 @@ +//--------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. +// +//--------------------------------------------------------------------- + +using Microsoft.OData.Edm.Validation; + +namespace Microsoft.OData.Edm.Csdl.CsdlSemantics +{ + internal class UnresolvedPropertyRef : BadElement, IUnresolvedElement, IEdmPropertyRef + { + public UnresolvedPropertyRef(IEdmStructuredType declaringType, string name, string alias, EdmLocation location) + : base(new EdmError[] + { + new EdmError(location, EdmErrorCode.BadUnresolvedPropertyRef, + Edm.Strings.Bad_UnresolvedPropertyRef(declaringType.FullTypeName(), name, alias)) + }) + { + } + + public IEdmStructuralProperty ReferencedProperty => null; + + public string PropertyAlias { get; } + + public string Name { get; } + } +} diff --git a/src/Microsoft.OData.Edm/Csdl/Semantics/CsdlSemanticsEntityTypeDefinition.cs b/src/Microsoft.OData.Edm/Csdl/Semantics/CsdlSemanticsEntityTypeDefinition.cs index c362edb1a7..fc222face5 100644 --- a/src/Microsoft.OData.Edm/Csdl/Semantics/CsdlSemanticsEntityTypeDefinition.cs +++ b/src/Microsoft.OData.Edm/Csdl/Semantics/CsdlSemanticsEntityTypeDefinition.cs @@ -14,7 +14,7 @@ namespace Microsoft.OData.Edm.Csdl.CsdlSemantics /// /// Provides semantics for CsdlEntityType. /// - internal class CsdlSemanticsEntityTypeDefinition : CsdlSemanticsStructuredTypeDefinition, IEdmEntityType, IEdmFullNamedElement + internal class CsdlSemanticsEntityTypeDefinition : CsdlSemanticsStructuredTypeDefinition, IEdmEntityType, IEdmFullNamedElement, IEdmKeyPropertyRef { private readonly CsdlEntityType entity; private readonly string fullName; @@ -23,8 +23,8 @@ internal class CsdlSemanticsEntityTypeDefinition : CsdlSemanticsStructuredTypeDe private static readonly Func ComputeBaseTypeFunc = (me) => me.ComputeBaseType(); private static readonly Func OnCycleBaseTypeFunc = (me) => new CyclicEntityType(me.GetCyclicBaseTypeName(me.entity.BaseTypeName), me.Location); - private readonly Cache> declaredKeyCache = new Cache>(); - private static readonly Func> ComputeDeclaredKeyFunc = (me) => me.ComputeDeclaredKey(); + private readonly Cache> declaredKeyCache = new Cache>(); + private static readonly Func> ComputeDeclaredKeyFunc = (me) => me.ComputeDeclaredKey(); public CsdlSemanticsEntityTypeDefinition(CsdlSemanticsSchema context, CsdlEntityType entity) : base(context, entity) @@ -72,6 +72,14 @@ public bool HasStream } public IEnumerable DeclaredKey + { + get + { + return this.DeclaredKeyRef?.Select(x => x.ReferencedProperty); + } + } + + public IEnumerable DeclaredKeyRef { get { @@ -79,6 +87,7 @@ public IEnumerable DeclaredKey } } + protected override CsdlStructuredType MyStructured { get { return this.entity; } @@ -105,32 +114,21 @@ private IEdmEntityType ComputeBaseType() return null; } - private IEnumerable ComputeDeclaredKey() + private IEnumerable ComputeDeclaredKey() { if (this.entity.Key != null) { - List key = new List(); + List key = new List(); foreach (CsdlPropertyReference keyProperty in this.entity.Key.Properties) { - IEdmStructuralProperty structuralProperty = this.FindProperty(keyProperty.PropertyName) as IEdmStructuralProperty; + IEdmStructuralProperty structuralProperty = FindKeyProperty(keyProperty.PropertyName); if (structuralProperty != null) { - key.Add(structuralProperty); + key.Add(new EdmPropertyRef(structuralProperty, keyProperty.PropertyName, keyProperty.PropertyAlias)); } else { - // If keyProperty is a duplicate, it will come back as non-structural from FindProperty, but it still might be structural - // inside the DeclaredProperties, so try it. If it is not in the DeclaredProperties or it is not structural there, - // then fall back to unresolved. - structuralProperty = this.DeclaredProperties.FirstOrDefault(p => p.Name == keyProperty.PropertyName) as IEdmStructuralProperty; - if (structuralProperty != null) - { - key.Add(structuralProperty); - } - else - { - key.Add(new UnresolvedProperty(this, keyProperty.PropertyName, this.Location)); - } + key.Add(new UnresolvedPropertyRef(this, keyProperty.PropertyName, keyProperty.PropertyAlias, this.Location)); } } @@ -139,5 +137,73 @@ private IEnumerable ComputeDeclaredKey() return null; } + + private IEdmStructuralProperty FindKeyProperty(string nameOrPath) + { + if (string.IsNullOrWhiteSpace(nameOrPath)) + { + return null; + } + + string[] segments = nameOrPath.Split('/'); + if (segments.Length == 1) + { + return this.FindProperty(nameOrPath) as IEdmStructuralProperty; + } + else + { + // OData spec says "The value of Name is a path expression leading to a primitive property." + // The segment in a path expression could be single value property name, collection value property name, type cast, ... + // However, for the key property reference path expression: + // 1) Collection value property name segment is invalid, right? + // 2) Type cast? reference a key on the sub type? it's valid but.... + // So far, let's skip those. + IEdmStructuredType edmStructuredType = this; + for (int i = 0; i < segments.Length; ++i) + { + if (edmStructuredType == null) + { + return null; + } + + string segment = segments[i]; + + if (segment.Contains(".")) + { + // a type cast, let's skip it. + continue; + } + + IEdmProperty edmProperty = FindPropertyOnType(edmStructuredType, segment); + if (i == segment.Length - 1) + { + return edmProperty as IEdmStructuralProperty; + } + else if (edmProperty != null) + { + // If the property is a collection value, let's move on using the element type of this collection + edmStructuredType = edmProperty.Type.ToStructuredType(); + } + else + { + return null; + } + } + } + + return null; + } + + private static IEdmProperty FindPropertyOnType(IEdmStructuredType structuredType, string name) + { + IEdmProperty property = structuredType.FindProperty(name); + + if (property == null) + { + property = structuredType.DeclaredProperties.FirstOrDefault(p => p.Name == name); + } + + return property; + } } } diff --git a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaJsonWriter.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaJsonWriter.cs index 5944ae5749..22a61c0da7 100644 --- a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaJsonWriter.cs +++ b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaJsonWriter.cs @@ -201,15 +201,28 @@ internal override void WriteDeclaredKeyPropertiesElementHeader() } /// - /// Write the Key property + /// Write the Key property ref /// - /// - internal override void WritePropertyRefElement(IEdmStructuralProperty property) + /// The property ref. + internal override void WritePropertyRefElement(IEdmPropertyRef propertyRef) { - // Key properties without a key alias are represented as strings containing the property name. - // Key properties with a key alias are represented as objects with one member whose name is the key alias and whose value is a string containing the path to the property. - // TODO: It seems the second one is not supported. - this.jsonWriter.WriteStringValue(property.Name); + if (propertyRef.PropertyAlias != null) + { + // Key properties with a key alias are represented as objects with one member + // whose name is the key alias and whose value is a string containing the path to the property. + this.jsonWriter.WriteStartObject(); + + this.jsonWriter.WritePropertyName(propertyRef.PropertyAlias); + + this.jsonWriter.WriteStringValue(propertyRef.Name); + + this.jsonWriter.WriteEndObject(); + } + else + { + // Key properties without a key alias are represented as strings containing the property name. + this.jsonWriter.WriteStringValue(propertyRef.Name); + } } /// diff --git a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaWriter.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaWriter.cs index a299e6a77e..89d6d9ba23 100644 --- a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaWriter.cs +++ b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaWriter.cs @@ -70,7 +70,7 @@ internal EdmModelCsdlSchemaWriter(IEdmModel model, Version edmVersion) internal abstract void WriteDeclaredKeyPropertiesElementHeader(); - internal abstract void WritePropertyRefElement(IEdmStructuralProperty property); + internal abstract void WritePropertyRefElement(IEdmPropertyRef propertyRef); internal abstract void WriteNavigationPropertyElementHeader(IEdmNavigationProperty property); diff --git a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaXmlWriter.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaXmlWriter.cs index 075c68d7f8..8f9a97ac8d 100644 --- a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaXmlWriter.cs +++ b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSchemaXmlWriter.cs @@ -150,10 +150,11 @@ internal override void WriteDeclaredKeyPropertiesElementHeader() this.xmlWriter.WriteStartElement(CsdlConstants.Element_Key); } - internal override void WritePropertyRefElement(IEdmStructuralProperty property) + internal override void WritePropertyRefElement(IEdmPropertyRef propertyRef) { this.xmlWriter.WriteStartElement(CsdlConstants.Element_PropertyRef); - this.WriteRequiredAttribute(CsdlConstants.Attribute_Name, property.Name, EdmValueWriter.StringAsXml); + this.WriteRequiredAttribute(CsdlConstants.Attribute_Name, propertyRef.Name, EdmValueWriter.StringAsXml); + this.WriteOptionalAttribute(CsdlConstants.Attribute_Alias, propertyRef.PropertyAlias, EdmValueWriter.StringAsXml); this.WriteEndElement(); } diff --git a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSerializationVisitor.cs b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSerializationVisitor.cs index 45b618822f..c317b3f99e 100644 --- a/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSerializationVisitor.cs +++ b/src/Microsoft.OData.Edm/Csdl/Serialization/EdmModelCsdlSerializationVisitor.cs @@ -145,7 +145,7 @@ protected override void ProcessEntityType(IEdmEntityType element) this.BeginElement(element, this.schemaWriter.WriteEntityTypeElementHeader); if (element.DeclaredKey != null && element.DeclaredKey.Any()) { - this.VisitEntityTypeDeclaredKey(element.DeclaredKey); + this.VisitEntityTypeDeclaredKey(element.DeclaredKeyRef()); } this.VisitProperties(element.DeclaredStructuralProperties().Cast()); @@ -680,18 +680,18 @@ private void ProcessFacets(IEdmTypeReference element, bool inlineType) } } - private void VisitEntityTypeDeclaredKey(IEnumerable keyProperties) + private void VisitEntityTypeDeclaredKey(IEnumerable keyProperties) { this.schemaWriter.WriteDeclaredKeyPropertiesElementHeader(); this.VisitPropertyRefs(keyProperties); this.schemaWriter.WriteArrayEndElement(); } - private void VisitPropertyRefs(IEnumerable properties) + private void VisitPropertyRefs(IEnumerable properties) { - foreach (IEdmStructuralProperty property in properties) + foreach (IEdmPropertyRef propertyRef in properties) { - this.schemaWriter.WritePropertyRefElement(property); + this.schemaWriter.WritePropertyRefElement(propertyRef); } } diff --git a/src/Microsoft.OData.Edm/ExtensionMethods/ExtensionMethods.cs b/src/Microsoft.OData.Edm/ExtensionMethods/ExtensionMethods.cs index a69c3bf04e..49cb818a8c 100644 --- a/src/Microsoft.OData.Edm/ExtensionMethods/ExtensionMethods.cs +++ b/src/Microsoft.OData.Edm/ExtensionMethods/ExtensionMethods.cs @@ -2124,6 +2124,52 @@ public static IEnumerable Key(this IEdmEntityType type) return Enumerable.Empty(); } + /// + /// Gets the declared key ref of the most defined entity with a declared key present. + /// + /// Reference to the calling object. + /// Key ref of this type. + public static IEnumerable KeyRef(this IEdmEntityType type) + { + EdmUtil.CheckArgumentNull(type, "type"); + IEdmEntityType checkingType = type; + while (checkingType != null) + { + IEnumerable keyRefs = checkingType.DeclaredKeyRef(); + + if (keyRefs != null) + { + return keyRefs; + } + + checkingType = checkingType.BaseEntityType(); + } + + return Enumerable.Empty(); + } + + /// + /// Gets the declared key ref on a defined entity. + /// + /// Reference to the calling object. + /// Key ref of this type. + public static IEnumerable DeclaredKeyRef(this IEdmEntityType entityType) + { + EdmUtil.CheckArgumentNull(entityType, "entityType"); + + if (entityType is IEdmKeyPropertyRef keyPropertyRef) + { + return keyPropertyRef.DeclaredKeyRef; + } + + if (entityType.DeclaredKey == null) + { + return null; + } + + return entityType.DeclaredKey.Select(k => new EdmPropertyRef(k)); + } + /// /// Determines whether the specified property is a key for its contained type. /// diff --git a/src/Microsoft.OData.Edm/Microsoft.OData.Edm.cs b/src/Microsoft.OData.Edm/Microsoft.OData.Edm.cs index 08ecc83344..288c5c86a7 100644 --- a/src/Microsoft.OData.Edm/Microsoft.OData.Edm.cs +++ b/src/Microsoft.OData.Edm/Microsoft.OData.Edm.cs @@ -299,6 +299,7 @@ internal sealed class EdmRes { internal const string Bad_UnresolvedEnumType = "Bad_UnresolvedEnumType"; internal const string Bad_UnresolvedEnumMember = "Bad_UnresolvedEnumMember"; internal const string Bad_UnresolvedProperty = "Bad_UnresolvedProperty"; + internal const string Bad_UnresolvedPropertyRef = "Bad_UnresolvedPropertyRef"; internal const string Bad_UnresolvedParameter = "Bad_UnresolvedParameter"; internal const string Bad_UnresolvedReturn = "Bad_UnresolvedReturn"; internal const string Bad_UnresolvedLabeledElement = "Bad_UnresolvedLabeledElement"; diff --git a/src/Microsoft.OData.Edm/Microsoft.OData.Edm.csproj b/src/Microsoft.OData.Edm/Microsoft.OData.Edm.csproj index 656049f997..6fbd387f73 100644 --- a/src/Microsoft.OData.Edm/Microsoft.OData.Edm.csproj +++ b/src/Microsoft.OData.Edm/Microsoft.OData.Edm.csproj @@ -112,4 +112,17 @@ + + + True + True + Microsoft.OData.Edm.tt + + + True + True + Parameterized.Microsoft.OData.Edm.tt + + + diff --git a/src/Microsoft.OData.Edm/Microsoft.OData.Edm.txt b/src/Microsoft.OData.Edm/Microsoft.OData.Edm.txt index 146b3339d8..85bdcf2757 100644 --- a/src/Microsoft.OData.Edm/Microsoft.OData.Edm.txt +++ b/src/Microsoft.OData.Edm/Microsoft.OData.Edm.txt @@ -302,6 +302,7 @@ Bad_UnresolvedEntityContainer=The entity container '{0}' could not be found. Bad_UnresolvedEnumType=The enum type '{0}' could not be found. Bad_UnresolvedEnumMember=The enum member '{0}' could not be found. Bad_UnresolvedProperty=The property '{0}' could not be found. +Bad_UnresolvedPropertyRef=The property ref on type '{0}' with name '{1}' and alias '{2}' could not be resolved. Bad_UnresolvedParameter=The parameter '{0}' could not be found. Bad_UnresolvedReturn=The return of operation '{0}' could not be found. Bad_UnresolvedLabeledElement=The labeled element '{0}' could not be found. diff --git a/src/Microsoft.OData.Edm/Parameterized.Microsoft.OData.Edm.cs b/src/Microsoft.OData.Edm/Parameterized.Microsoft.OData.Edm.cs index 11f6689f6a..27ec4c8cff 100644 --- a/src/Microsoft.OData.Edm/Parameterized.Microsoft.OData.Edm.cs +++ b/src/Microsoft.OData.Edm/Parameterized.Microsoft.OData.Edm.cs @@ -2393,6 +2393,14 @@ internal static string Bad_UnresolvedProperty(object p0) return Microsoft.OData.Edm.EdmRes.GetString(Microsoft.OData.Edm.EdmRes.Bad_UnresolvedProperty, p0); } + /// + /// A string like "The property ref on type '{0}' with name '{1}' and alias '{2}' could not be resolved." + /// + internal static string Bad_UnresolvedPropertyRef(object p0, object p1, object p2) + { + return Microsoft.OData.Edm.EdmRes.GetString(Microsoft.OData.Edm.EdmRes.Bad_UnresolvedPropertyRef, p0, p1, p2); + } + /// /// A string like "The parameter '{0}' could not be found." /// diff --git a/src/Microsoft.OData.Edm/PublicAPI/net45/PublicAPI.Unshipped.txt b/src/Microsoft.OData.Edm/PublicAPI/net45/PublicAPI.Unshipped.txt index 5f282702bb..c71e219dc1 100644 --- a/src/Microsoft.OData.Edm/PublicAPI/net45/PublicAPI.Unshipped.txt +++ b/src/Microsoft.OData.Edm/PublicAPI/net45/PublicAPI.Unshipped.txt @@ -1 +1,18 @@ - \ No newline at end of file +Microsoft.OData.Edm.EdmEntityType.AddKeys(params Microsoft.OData.Edm.IEdmPropertyRef[] keyProperties) -> void +Microsoft.OData.Edm.EdmEntityType.AddKeys(System.Collections.Generic.IEnumerable keyProperties) -> void +Microsoft.OData.Edm.EdmPropertyRef +Microsoft.OData.Edm.EdmPropertyRef.EdmPropertyRef(Microsoft.OData.Edm.IEdmStructuralProperty property) -> void +Microsoft.OData.Edm.EdmPropertyRef.EdmPropertyRef(Microsoft.OData.Edm.IEdmStructuralProperty property, string alias) -> void +Microsoft.OData.Edm.EdmPropertyRef.EdmPropertyRef(Microsoft.OData.Edm.IEdmStructuralProperty property, string name, string alias) -> void +Microsoft.OData.Edm.EdmPropertyRef.Name.get -> string +Microsoft.OData.Edm.EdmPropertyRef.PropertyAlias.get -> string +Microsoft.OData.Edm.EdmPropertyRef.ReferencedProperty.get -> Microsoft.OData.Edm.IEdmStructuralProperty +Microsoft.OData.Edm.IEdmKeyPropertyRef +Microsoft.OData.Edm.IEdmKeyPropertyRef.DeclaredKeyRef.get -> System.Collections.Generic.IEnumerable +Microsoft.OData.Edm.IEdmPropertyRef +Microsoft.OData.Edm.IEdmPropertyRef.PropertyAlias.get -> string +Microsoft.OData.Edm.IEdmPropertyRef.ReferencedProperty.get -> Microsoft.OData.Edm.IEdmStructuralProperty +Microsoft.OData.Edm.Validation.EdmErrorCode.BadUnresolvedPropertyRef = 412 -> Microsoft.OData.Edm.Validation.EdmErrorCode +static Microsoft.OData.Edm.ExtensionMethods.DeclaredKeyRef(this Microsoft.OData.Edm.IEdmEntityType entityType) -> System.Collections.Generic.IEnumerable +static Microsoft.OData.Edm.ExtensionMethods.KeyRef(this Microsoft.OData.Edm.IEdmEntityType type) -> System.Collections.Generic.IEnumerable +virtual Microsoft.OData.Edm.EdmEntityType.DeclaredKeyRef.get -> System.Collections.Generic.IEnumerable \ No newline at end of file diff --git a/src/Microsoft.OData.Edm/PublicAPI/netstandard1.1/PublicAPI.Unshipped.txt b/src/Microsoft.OData.Edm/PublicAPI/netstandard1.1/PublicAPI.Unshipped.txt index 5f282702bb..c71e219dc1 100644 --- a/src/Microsoft.OData.Edm/PublicAPI/netstandard1.1/PublicAPI.Unshipped.txt +++ b/src/Microsoft.OData.Edm/PublicAPI/netstandard1.1/PublicAPI.Unshipped.txt @@ -1 +1,18 @@ - \ No newline at end of file +Microsoft.OData.Edm.EdmEntityType.AddKeys(params Microsoft.OData.Edm.IEdmPropertyRef[] keyProperties) -> void +Microsoft.OData.Edm.EdmEntityType.AddKeys(System.Collections.Generic.IEnumerable keyProperties) -> void +Microsoft.OData.Edm.EdmPropertyRef +Microsoft.OData.Edm.EdmPropertyRef.EdmPropertyRef(Microsoft.OData.Edm.IEdmStructuralProperty property) -> void +Microsoft.OData.Edm.EdmPropertyRef.EdmPropertyRef(Microsoft.OData.Edm.IEdmStructuralProperty property, string alias) -> void +Microsoft.OData.Edm.EdmPropertyRef.EdmPropertyRef(Microsoft.OData.Edm.IEdmStructuralProperty property, string name, string alias) -> void +Microsoft.OData.Edm.EdmPropertyRef.Name.get -> string +Microsoft.OData.Edm.EdmPropertyRef.PropertyAlias.get -> string +Microsoft.OData.Edm.EdmPropertyRef.ReferencedProperty.get -> Microsoft.OData.Edm.IEdmStructuralProperty +Microsoft.OData.Edm.IEdmKeyPropertyRef +Microsoft.OData.Edm.IEdmKeyPropertyRef.DeclaredKeyRef.get -> System.Collections.Generic.IEnumerable +Microsoft.OData.Edm.IEdmPropertyRef +Microsoft.OData.Edm.IEdmPropertyRef.PropertyAlias.get -> string +Microsoft.OData.Edm.IEdmPropertyRef.ReferencedProperty.get -> Microsoft.OData.Edm.IEdmStructuralProperty +Microsoft.OData.Edm.Validation.EdmErrorCode.BadUnresolvedPropertyRef = 412 -> Microsoft.OData.Edm.Validation.EdmErrorCode +static Microsoft.OData.Edm.ExtensionMethods.DeclaredKeyRef(this Microsoft.OData.Edm.IEdmEntityType entityType) -> System.Collections.Generic.IEnumerable +static Microsoft.OData.Edm.ExtensionMethods.KeyRef(this Microsoft.OData.Edm.IEdmEntityType type) -> System.Collections.Generic.IEnumerable +virtual Microsoft.OData.Edm.EdmEntityType.DeclaredKeyRef.get -> System.Collections.Generic.IEnumerable \ No newline at end of file diff --git a/src/Microsoft.OData.Edm/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/Microsoft.OData.Edm/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index 5f282702bb..c71e219dc1 100644 --- a/src/Microsoft.OData.Edm/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/Microsoft.OData.Edm/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1 +1,18 @@ - \ No newline at end of file +Microsoft.OData.Edm.EdmEntityType.AddKeys(params Microsoft.OData.Edm.IEdmPropertyRef[] keyProperties) -> void +Microsoft.OData.Edm.EdmEntityType.AddKeys(System.Collections.Generic.IEnumerable keyProperties) -> void +Microsoft.OData.Edm.EdmPropertyRef +Microsoft.OData.Edm.EdmPropertyRef.EdmPropertyRef(Microsoft.OData.Edm.IEdmStructuralProperty property) -> void +Microsoft.OData.Edm.EdmPropertyRef.EdmPropertyRef(Microsoft.OData.Edm.IEdmStructuralProperty property, string alias) -> void +Microsoft.OData.Edm.EdmPropertyRef.EdmPropertyRef(Microsoft.OData.Edm.IEdmStructuralProperty property, string name, string alias) -> void +Microsoft.OData.Edm.EdmPropertyRef.Name.get -> string +Microsoft.OData.Edm.EdmPropertyRef.PropertyAlias.get -> string +Microsoft.OData.Edm.EdmPropertyRef.ReferencedProperty.get -> Microsoft.OData.Edm.IEdmStructuralProperty +Microsoft.OData.Edm.IEdmKeyPropertyRef +Microsoft.OData.Edm.IEdmKeyPropertyRef.DeclaredKeyRef.get -> System.Collections.Generic.IEnumerable +Microsoft.OData.Edm.IEdmPropertyRef +Microsoft.OData.Edm.IEdmPropertyRef.PropertyAlias.get -> string +Microsoft.OData.Edm.IEdmPropertyRef.ReferencedProperty.get -> Microsoft.OData.Edm.IEdmStructuralProperty +Microsoft.OData.Edm.Validation.EdmErrorCode.BadUnresolvedPropertyRef = 412 -> Microsoft.OData.Edm.Validation.EdmErrorCode +static Microsoft.OData.Edm.ExtensionMethods.DeclaredKeyRef(this Microsoft.OData.Edm.IEdmEntityType entityType) -> System.Collections.Generic.IEnumerable +static Microsoft.OData.Edm.ExtensionMethods.KeyRef(this Microsoft.OData.Edm.IEdmEntityType type) -> System.Collections.Generic.IEnumerable +virtual Microsoft.OData.Edm.EdmEntityType.DeclaredKeyRef.get -> System.Collections.Generic.IEnumerable \ No newline at end of file diff --git a/src/Microsoft.OData.Edm/Schema/BadEntityType.cs b/src/Microsoft.OData.Edm/Schema/BadEntityType.cs index 0f879ceb02..80fa4c3ee6 100644 --- a/src/Microsoft.OData.Edm/Schema/BadEntityType.cs +++ b/src/Microsoft.OData.Edm/Schema/BadEntityType.cs @@ -6,33 +6,26 @@ using System.Collections.Generic; using Microsoft.OData.Edm.Validation; -using Microsoft.OData.Edm.Vocabularies; namespace Microsoft.OData.Edm { /// /// Represents a semantically invalid EDM entity type. /// - internal class BadEntityType : BadNamedStructuredType, IEdmEntityType + internal class BadEntityType : BadNamedStructuredType, IEdmEntityType, IEdmKeyPropertyRef { public BadEntityType(string qualifiedName, IEnumerable errors) : base(qualifiedName, errors) { } - public IEnumerable DeclaredKey - { - get { return null; } - } + public IEnumerable DeclaredKey => null; - public override EdmTypeKind TypeKind - { - get { return EdmTypeKind.Entity; } - } + public IEnumerable DeclaredKeyRef => null; + + public override EdmTypeKind TypeKind => EdmTypeKind.Entity; + + public bool HasStream => false; - public bool HasStream - { - get { return false; } - } } } diff --git a/src/Microsoft.OData.Edm/Schema/CoreModel/EdmCoreModelEntityType.cs b/src/Microsoft.OData.Edm/Schema/CoreModel/EdmCoreModelEntityType.cs index ac497ae080..3ad35c4ee9 100644 --- a/src/Microsoft.OData.Edm/Schema/CoreModel/EdmCoreModelEntityType.cs +++ b/src/Microsoft.OData.Edm/Schema/CoreModel/EdmCoreModelEntityType.cs @@ -14,7 +14,7 @@ namespace Microsoft.OData.Edm /// /// The built-in Edm.EntityType abstract type in the core model. /// - internal sealed class EdmCoreModelEntityType : EdmType, IEdmEntityType, IEdmCoreModelElement, IEdmFullNamedElement + internal sealed class EdmCoreModelEntityType : EdmType, IEdmEntityType, IEdmCoreModelElement, IEdmFullNamedElement, IEdmKeyPropertyRef { /// /// The core Edm.EntityType singleton. @@ -122,6 +122,11 @@ public IEnumerable DeclaredKey get { return Enumerable.Empty(); } } + /// + /// Gets the key property ref immediately within this type. + /// + public IEnumerable DeclaredKeyRef => Enumerable.Empty(); + /// /// Searches for a structural or navigation property with the given name in this type. /// diff --git a/src/Microsoft.OData.Edm/Schema/EdmEntityType.cs b/src/Microsoft.OData.Edm/Schema/EdmEntityType.cs index 56b36300b3..3fc6a1f858 100644 --- a/src/Microsoft.OData.Edm/Schema/EdmEntityType.cs +++ b/src/Microsoft.OData.Edm/Schema/EdmEntityType.cs @@ -7,19 +7,20 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.Linq; namespace Microsoft.OData.Edm { /// /// Represents a definition of an EDM entity type. /// - public class EdmEntityType : EdmStructuredType, IEdmEntityType, IEdmFullNamedElement + public class EdmEntityType : EdmStructuredType, IEdmEntityType, IEdmFullNamedElement, IEdmKeyPropertyRef { private readonly string namespaceName; private readonly string name; private readonly string fullName; private readonly bool hasStream; - private List declaredKey; + private List declaredKey; /// /// Initializes a new instance of the class. @@ -80,6 +81,14 @@ public EdmEntityType(string namespaceName, string name, IEdmEntityType baseType, /// Gets the structural properties of the entity type that make up the entity key. /// public virtual IEnumerable DeclaredKey + { + get { return this.DeclaredKeyRef?.Select(k => k.ReferencedProperty); } + } + + /// + /// Gets the property refs of the entity type that make up the entity key. + /// + public virtual IEnumerable DeclaredKeyRef { get { return this.declaredKey; } } @@ -154,10 +163,39 @@ public void AddKeys(IEnumerable keyProperties) { if (this.declaredKey == null) { - this.declaredKey = new List(); + this.declaredKey = new List(); + } + + // or, we should search if the property.DeclaringType != this + this.declaredKey.Add(new EdmPropertyRef(property)); + } + } + + /// + /// Adds the to the key of this entity type. + /// + /// The key properties. + public void AddKeys(params IEdmPropertyRef[] keyProperties) + { + this.AddKeys((IEnumerable)keyProperties); + } + + /// + /// Adds the to the key of this entity type. + /// + /// The key properties. + public void AddKeys(IEnumerable keyProperties) + { + EdmUtil.CheckArgumentNull(keyProperties, "keyProperties"); + + foreach (IEdmPropertyRef propertyRef in keyProperties) + { + if (this.declaredKey == null) + { + this.declaredKey = new List(); } - this.declaredKey.Add(property); + this.declaredKey.Add(propertyRef); } } diff --git a/src/Microsoft.OData.Edm/Schema/EdmPropertyRef.cs b/src/Microsoft.OData.Edm/Schema/EdmPropertyRef.cs new file mode 100644 index 0000000000..8cb72e0abb --- /dev/null +++ b/src/Microsoft.OData.Edm/Schema/EdmPropertyRef.cs @@ -0,0 +1,64 @@ +//--------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. +// +//--------------------------------------------------------------------- + +namespace Microsoft.OData.Edm +{ + /// + /// Represents a definition of an EDM property reference element. + /// + public class EdmPropertyRef : IEdmPropertyRef + { + /// + /// Initializes a new instance of the class. + /// + /// The referenced property. + public EdmPropertyRef(IEdmStructuralProperty property) + : this(property, property?.Name, alias: null) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The referenced property. + /// The property reference alias. + public EdmPropertyRef(IEdmStructuralProperty property, string alias) + : this(property, property?.Name, alias) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The referenced property. + /// The property reference name. + /// The property reference alias. + public EdmPropertyRef(IEdmStructuralProperty property, string name, string alias) + { + EdmUtil.CheckArgumentNull(property, "property"); + EdmUtil.CheckArgumentNull(name, "name"); + + ReferencedProperty = property; + Name = name; + PropertyAlias = alias; + } + + /// + /// Gets the referenced property. + /// + public IEdmStructuralProperty ReferencedProperty { get; } + + /// + /// Gets the value of Name is a path expression leading to a primitive property. + /// + public string Name { get; } + + /// + /// Gets the alias. + /// + public string PropertyAlias { get; } + } +} diff --git a/src/Microsoft.OData.Edm/Schema/Interfaces/IEdmKeyPropertyRef.cs b/src/Microsoft.OData.Edm/Schema/Interfaces/IEdmKeyPropertyRef.cs new file mode 100644 index 0000000000..e557b7ccc0 --- /dev/null +++ b/src/Microsoft.OData.Edm/Schema/Interfaces/IEdmKeyPropertyRef.cs @@ -0,0 +1,22 @@ +//--------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. +// +//--------------------------------------------------------------------- + +using System.Collections.Generic; + +namespace Microsoft.OData.Edm +{ + /// + /// Represents a definition of key references of an entity type. + /// In the next major release, we should remove this interface and move the members into IEdmEntityType. + /// + public interface IEdmKeyPropertyRef + { + /// + /// Gets the declared key references. + /// + IEnumerable DeclaredKeyRef { get; } + } +} diff --git a/src/Microsoft.OData.Edm/Schema/Interfaces/IEdmPropertyRef.cs b/src/Microsoft.OData.Edm/Schema/Interfaces/IEdmPropertyRef.cs new file mode 100644 index 0000000000..217a653cfd --- /dev/null +++ b/src/Microsoft.OData.Edm/Schema/Interfaces/IEdmPropertyRef.cs @@ -0,0 +1,25 @@ +//--------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. +// +//--------------------------------------------------------------------- + +namespace Microsoft.OData.Edm +{ + /// + /// Represents a property reference element. + /// The edm:PropertyRef element MUST contain the Name attribute and MAY contain the Alias attribute. + /// + public interface IEdmPropertyRef : IEdmNamedElement + { + /// + /// Gets the property referenced structural property. + /// + IEdmStructuralProperty ReferencedProperty { get; } + + /// + /// Gets the value of Alias + /// + string PropertyAlias { get; } + } +} diff --git a/src/Microsoft.OData.Edm/Validation/EdmErrorCode.cs b/src/Microsoft.OData.Edm/Validation/EdmErrorCode.cs index e81a1ae560..7bce4fb0db 100644 --- a/src/Microsoft.OData.Edm/Validation/EdmErrorCode.cs +++ b/src/Microsoft.OData.Edm/Validation/EdmErrorCode.cs @@ -1437,5 +1437,10 @@ public enum EdmErrorCode /// A recursive complex-typed property must be optional. /// RecursiveComplexTypedPropertyMustBeOptional, + + /// + /// Could not resolve a property ref with that name + /// + BadUnresolvedPropertyRef, } } diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlReaderJsonTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlReaderJsonTests.cs index 476759212f..189a15ae31 100644 --- a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlReaderJsonTests.cs +++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlReaderJsonTests.cs @@ -24,6 +24,56 @@ namespace Microsoft.OData.Edm.Tests.Csdl { public class CsdlReaderJsonTests { + [Fact] + public void ReadKeyAliasInJsonTest() + { + var jsonCsdl = @"{ + ""$Version"": ""4.0"", + ""NS"": { + ""EntityInfo"": { + ""$Kind"": ""ComplexType"", + ""ID"": { + ""$Type"": ""Edm.Int32"" + }, + ""Created"": { + ""$Type"": ""Edm.DateTimeOffset"", + ""$Nullable"": true, + ""$Precision"": 0 + } + }, + ""Category"": { + ""$Kind"": ""EntityType"", + ""$Key"": [ + ""ID"", + { + ""EntityInfoID"": ""Info/ID"" + } + ], + ""Info"": { + ""$Type"": ""NS.EntityInfo"" + }, + ""Name"": { + ""$Nullable"": true + }, + ""ID"": {} + } + } +}"; + + IEdmModel model = Parse(jsonCsdl); + + // Act & Assert + IEdmEntityType categoryType = model.SchemaElements.OfType().First(); + + // Two "ID" because the referenced property names are "ID" in entity type and complex type. + Assert.Equal(new string[] { "NS.Category.ID", "NS.EntityInfo.ID" }, + categoryType.DeclaredKey.Select(k => $"{k.DeclaringType.FullTypeName()}.{k.Name}")); + + IEnumerable propertyRefs = categoryType.DeclaredKeyRef(); + Assert.Equal(new string[] { "ID", "Info/ID" }, propertyRefs.Select(k => k.Name)); + Assert.Equal(new string[] { "--", "EntityInfoID" }, propertyRefs.Select(k => k.PropertyAlias ?? "--" )); + } + [Fact] public void ReadNavigationPropertyPartnerInJsonTest() { diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlReaderTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlReaderTests.cs index 95fcddd076..cf2e75afe4 100644 --- a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlReaderTests.cs +++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlReaderTests.cs @@ -907,6 +907,45 @@ public void ParsingOptionalParametersShouldSucceed() Assert.Equal("Smith", optionalParamWithDefault.DefaultValueString); } + [Fact] + public void ParsingXmlWithKeyAliasOnPropertyOnComplex() + { + // Arrange + string csdlWithKeyAlias = "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + + // Act + IEdmModel model = CsdlReader.Parse(XElement.Parse(csdlWithKeyAlias).CreateReader()); + + // Assert + // There's only one entity type and one complex type + IEdmEntityType entityType = model.SchemaElements.OfType().First(); + IEdmComplexType complexType = model.SchemaElements.OfType().First(); + + IEdmProperty complexIdProperty = complexType.FindProperty("ID"); + + IEdmStructuralProperty keyProperty = Assert.Single(entityType.DeclaredKey); + Assert.Same(complexIdProperty, keyProperty); + + IEdmPropertyRef keyPropertyRef = Assert.Single(entityType.DeclaredKeyRef()); + Assert.Same(complexIdProperty, keyPropertyRef.ReferencedProperty); + Assert.Equal("Info/ID", keyPropertyRef.Name); + Assert.Equal("ComID", keyPropertyRef.PropertyAlias); + } + [Theory] [InlineData(EdmVocabularyAnnotationSerializationLocation.Inline)] [InlineData(EdmVocabularyAnnotationSerializationLocation.OutOfLine)] diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.cs index 2e25e35007..ccb4c6589e 100644 --- a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.cs +++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/CsdlWriterTests.cs @@ -2156,6 +2156,148 @@ public void CanWriteUrlEscapeFunction() }"); } + [Fact] + public void CanWriteEntityType_WithASimpleKey_ReferencingAPropertyOfAComplex() + { + // Arrange + EdmModel model = new EdmModel(); + EdmComplexType complex = new EdmComplexType("NS", "EntityInfo"); + var key = complex.AddStructuralProperty("ID", EdmCoreModel.Instance.GetInt32(false)); + complex.AddStructuralProperty("Created", EdmCoreModel.Instance.GetDateTimeOffset(true)); + model.AddElement(complex); + + EdmEntityType entity = new EdmEntityType("NS", "Category"); + entity.AddStructuralProperty("Info", new EdmComplexTypeReference(complex, false)); + entity.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(true)); + model.AddElement(entity); + entity.AddKeys(new EdmPropertyRef(key, "Info/ID", "EntityInfoID")); + + // Act & Assert for XML + WriteAndVerifyXml(model, "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""); + + // Act & Assert for JSON + WriteAndVerifyJson(model, @"{ + ""$Version"": ""4.0"", + ""NS"": { + ""EntityInfo"": { + ""$Kind"": ""ComplexType"", + ""ID"": { + ""$Type"": ""Edm.Int32"" + }, + ""Created"": { + ""$Type"": ""Edm.DateTimeOffset"", + ""$Nullable"": true, + ""$Precision"": 0 + } + }, + ""Category"": { + ""$Kind"": ""EntityType"", + ""$Key"": [ + { + ""EntityInfoID"": ""Info/ID"" + } + ], + ""Info"": { + ""$Type"": ""NS.EntityInfo"" + }, + ""Name"": { + ""$Nullable"": true + } + } + } +}"); + } + + [Fact] + public void CanWriteEntityType_WithAMultipleKeys_ReferencingAPropertyOfAComplex() + { + // Arrange + EdmModel model = new EdmModel(); + EdmComplexType complex = new EdmComplexType("NS", "EntityInfo"); + var key = complex.AddStructuralProperty("ID", EdmCoreModel.Instance.GetInt32(false)); + complex.AddStructuralProperty("Created", EdmCoreModel.Instance.GetDateTimeOffset(true)); + model.AddElement(complex); + + EdmEntityType entity = new EdmEntityType("NS", "Category"); + entity.AddStructuralProperty("Info", new EdmComplexTypeReference(complex, false)); + entity.AddStructuralProperty("Name", EdmCoreModel.Instance.GetString(true)); + var id = entity.AddStructuralProperty("ID", EdmCoreModel.Instance.GetString(false)); + model.AddElement(entity); + entity.AddKeys( + new EdmPropertyRef(id), + new EdmPropertyRef(key, "Info/ID", "EntityInfoID")); + + // Act & Assert for XML + WriteAndVerifyXml(model, "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + +""); + + // Act & Assert for JSON + WriteAndVerifyJson(model, @"{ + ""$Version"": ""4.0"", + ""NS"": { + ""EntityInfo"": { + ""$Kind"": ""ComplexType"", + ""ID"": { + ""$Type"": ""Edm.Int32"" + }, + ""Created"": { + ""$Type"": ""Edm.DateTimeOffset"", + ""$Nullable"": true, + ""$Precision"": 0 + } + }, + ""Category"": { + ""$Kind"": ""EntityType"", + ""$Key"": [ + ""ID"", + { + ""EntityInfoID"": ""Info/ID"" + } + ], + ""Info"": { + ""$Type"": ""NS.EntityInfo"" + }, + ""Name"": { + ""$Nullable"": true + }, + ""ID"": {} + } + } +}"); + } + [Fact] public void CanWriteAnnotationPathExpression() { diff --git a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/Semantics/CsdlSemanticsNavigationPropertyTests.cs b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/Semantics/CsdlSemanticsNavigationPropertyTests.cs index 7e212eef5a..cb4dc74c7e 100644 --- a/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/Semantics/CsdlSemanticsNavigationPropertyTests.cs +++ b/test/FunctionalTests/Microsoft.OData.Edm.Tests/Csdl/Semantics/CsdlSemanticsNavigationPropertyTests.cs @@ -37,7 +37,7 @@ public CsdlSemanticsNavigationPropertyTests() var idProperty = new CsdlProperty("ID", new CsdlNamedTypeReference("Edm.Int32", false, null), null, null); var fkProperty = new CsdlProperty("FK", new CsdlNamedTypeReference("Edm.Int32", false, null), null, null); - this.csdlEntityType = new CsdlEntityType("EntityType", null, false, false, false, new CsdlKey(new[] { new CsdlPropertyReference("ID", null) }, null), new[] { idProperty, fkProperty }, new[] { collectionProperty, referenceProperty, navigationWithoutPartner }, null); + this.csdlEntityType = new CsdlEntityType("EntityType", null, false, false, false, new CsdlKey(new[] { new CsdlPropertyReference("ID", null, null) }, null), new[] { idProperty, fkProperty }, new[] { collectionProperty, referenceProperty, navigationWithoutPartner }, null); var csdlSchema = new CsdlSchema("FQ.NS", null, null, new[] { this.csdlEntityType }, Enumerable.Empty(), Enumerable.Empty(),Enumerable.Empty(),Enumerable.Empty(),Enumerable.Empty(), Enumerable.Empty(), null); var csdlModel = new CsdlModel();