public override Object Clone() { NodeFacet clone = (NodeFacet)base.Clone(); clone._value = (NodeValue)this.Value.Clone(); return(clone); }
public ConcurrencyAttribute(ResourceType type, IEnumerable <string> propertyNames) : base("ETag") { etagProperties = type.Properties.OfType <ResourceProperty>().Where(p => propertyNames.Contains(p.Name)).ToList(); etagProperties.ForEach(p => p.Facets.Add(NodeFacet.ConcurrencyModeFixed())); this.orderedParams = etagProperties.Select(p => "\"" + p.Name + "\"").ToList(); }
protected override void WorkspaceCallback(Workspace workspace) { ServiceContainer sc = workspace.ServiceContainer; Nodes <ResourceContainer> containers = sc.ResourceContainers; ResourceContainer builds = containers["Builds"]; ResourceContainer run1s = containers["Run1s"]; ResourceContainer run2s = containers["Run2s"]; ResourceContainer run3s = containers["Run3s"]; ResourceContainer test1s = containers["Test1s"]; ResourceContainer test2s = containers["Test2s"]; ResourceContainer test3s = containers["Test3s"]; ResourceContainer test4s = containers["Test4s"]; ResourceContainer test5s = containers["Test5s"]; ResourceContainer test6s = containers["Test6s"]; ResourceContainer test7s = containers["Test7s"]; ResourceContainer test8s = containers["Test8s"]; ResourceContainer test9s = containers["Test9s"]; sc.Facets.Add(NodeFacet.Attribute(new ContainmentAttribute(builds, run1s, true))); sc.Facets.Add(NodeFacet.Attribute(new ContainmentAttribute(run1s, test1s, true))); sc.Facets.Add(NodeFacet.Attribute(new ContainmentAttribute(run1s, test2s))); sc.Facets.Add(NodeFacet.Attribute(new ContainmentAttribute(run1s, test3s, false))); sc.Facets.Add(NodeFacet.Attribute(new ContainmentAttribute(builds, run2s))); sc.Facets.Add(NodeFacet.Attribute(new ContainmentAttribute(run2s, test4s, true))); sc.Facets.Add(NodeFacet.Attribute(new ContainmentAttribute(run2s, test5s))); sc.Facets.Add(NodeFacet.Attribute(new ContainmentAttribute(run2s, test6s, false))); sc.Facets.Add(NodeFacet.Attribute(new ContainmentAttribute(builds, run3s, false))); sc.Facets.Add(NodeFacet.Attribute(new ContainmentAttribute(run3s, test7s, true))); sc.Facets.Add(NodeFacet.Attribute(new ContainmentAttribute(run3s, test8s))); sc.Facets.Add(NodeFacet.Attribute(new ContainmentAttribute(run3s, test9s, true))); }
//--------------------------------------------------------------------- // Adds concurrency attributes to resource types. //--------------------------------------------------------------------- protected virtual void AddConcurrencyAttributes(Workspace w) { if (!GetType().Name.Contains("Concurrency")) { return; } HashSet <ResourceType> typesWithETags = new HashSet <ResourceType>(); foreach (ResourceContainer container in w.ServiceContainer.ResourceContainers) { ResourceType baseType = container.BaseType; if (!typesWithETags.Add(baseType)) { continue; } // set up ETags NodeType[] etagTypes = new NodeType[] { Clr.Types.String, Clr.Types.Int16, Clr.Types.Int32, Clr.Types.Int64, Clr.Types.Guid }; List <ResourceProperty> possibleETagProperties = baseType.Properties.OfType <ResourceProperty>() .Where(p => etagTypes.Contains(p.Type) && !p.IsComplexType && !p.IsNavigation && p.PrimaryKey == null && p.Facets.IsDeclaredProperty && !p.Facets.FixedLength && p.ResourceType == baseType && p.Facets.UnderlyingType == UnderlyingType.Same && !p.Facets.IsStoreBlob && (p.Type != Clr.Types.String || (p.Facets.MaxSize.HasValue && p.Facets.MaxSize.Value < 512))) .ToList(); if (possibleETagProperties.Any()) { baseType.Facets.Add(NodeFacet.Attribute(new ConcurrencyAttribute(baseType, possibleETagProperties.Choose(2).Select(p => p.Name).ToArray()))); } } }
//--------------------------------------------------------------------- // Adds blobs attributes to resource types. //--------------------------------------------------------------------- protected virtual void AddBlobsAttributes(Workspace w, params string[] typeNames) { foreach (string typeName in typeNames) { ResourceType type = w.ServiceContainer.ResourceTypes.Where(t => t.Name == typeName).First(); type.Facets.Add(NodeFacet.Attribute(new BlobsAttribute(type))); } }
// Turns a resource type into an MLE. private static void MakeMLE(Workspace w, string typeName) { // Add blob attribute. ResourceType type = w.ServiceContainer.ResourceTypes.Where(p => p.Name == typeName).First(); type.Facets.Add(NodeFacet.Attribute(new BlobsAttribute(type))); AstoriaTestLog.WriteLineIgnore("MLE type: " + type.Name); }
//Data //Constructor public LinqToSqlXml() : base(NodeFacet.Nullable(true)) { Assembly dataLinqAssembly = TypeUtil.GetAssembly(this.Namespace); if (dataLinqAssembly == null) { dataLinqAssembly = Assembly.LoadWithPartialName(this.Namespace); } this.ClrType = dataLinqAssembly.GetType("System.Xml.Linq.XElement"); }
public OpenTypeResourceAttribute(ResourceType type, string propertyName, Func <ResourceProperty, bool> declaredPropertyFilter) : base("OpenType") { this.orderedParams = new List <string>() { "\"" + propertyName + "\"" }; this.PropertyName = propertyName; type.Facets.Add(NodeFacet.IsOpenType()); foreach (ResourceProperty property in type.Properties.OfType <ResourceProperty>()) { if (!declaredPropertyFilter(property)) { property.Facets.IsDeclaredProperty = false; } } }
private ContainmentAttribute(bool canonical, bool topLevelAccess, ResourceContainer parent, ResourceContainer child) : base(canonical ? "CanonicalAccessPath" : "AccessPath") { parent.Workspace.Settings.HasContainment = true; this.ParentContainer = parent; this.ChildContainer = child; this.Canonical = canonical; this.TopLevelAccess = topLevelAccess; this.KeyMapping = new Dictionary <string, string>(); this.InferProperties(); if (canonical) { this.namedParams.Add("TopLevelAccess", topLevelAccess.ToString().ToLowerInvariant()); } ParentNavigationProperty.Facets.Add(NodeFacet.CanonicalAccessPath(Canonical)); ChildContainer.BaseType.Facets.Add(NodeFacet.TopLevelAccess(topLevelAccess)); }
private void SetupConcurrencyTokens(ResourceType resourceType) { List <string> mapTheseProperties = new List <string>(); if (UseInheritedTypes) { if (!AnyBaseTypeHasConcurrencyFacets(resourceType) && !resourceType.HasDerivedTypes && resourceType.BaseType == null) { foreach (ResourceProperty property in resourceType.Properties.OfType <ResourceProperty>() .Where( rp => rp.PrimaryKey == null && !rp.IsNavigation && !rp.IsComplexType && rp.Type.ClrType != typeof(System.Byte[]) && rp.Facets.MaxSize == null && !rp.Facets.IsStoreBlob) ) { mapTheseProperties.Add(property.Name); } resourceType.Facets.Add(NodeFacet.Attribute(new ConcurrencyAttribute(resourceType, mapTheseProperties))); } } else { foreach (ResourceProperty property in resourceType.Properties.OfType <ResourceProperty>() .Where( rp => rp.PrimaryKey == null && !rp.IsNavigation && !rp.IsComplexType && rp.Type.ClrType != typeof(System.Byte[]) && rp.Facets.MaxSize == null && !rp.Facets.IsStoreBlob) ) { mapTheseProperties.Add(property.Name); } if (resourceType.BaseType == null) { resourceType.Facets.Add(NodeFacet.Attribute(new ConcurrencyAttribute(resourceType, mapTheseProperties))); } } }
public static void SetupDefaultOpenTypeAttributes(Workspace w) { if (w.DataLayerProviderKind != DataLayerProviderKind.NonClr) { AstoriaTestLog.FailAndThrow("Open types not supported for data-layers other than NonCLR"); } #if !ClientSKUFramework // let the open types tests do their own thing if (w is OpenTypesWorkspace) { return; } #endif if (w.Name.Equals("Northwind", StringComparison.InvariantCultureIgnoreCase)) { foreach (ResourceType type in w.ServiceContainer.ResourceTypes.Distinct().Where(t => !t.Facets.IsOpenType)) { type.Facets.Add(NodeFacet.Attribute(new OpenTypeResourceAttribute(type, (rp => rp.IsNavigation || rp.PrimaryKey != null || rp.Facets.ConcurrencyModeFixed)))); } } else if (w.Name.Equals("Aruba", StringComparison.InvariantCultureIgnoreCase)) { foreach (ResourceType type in w.ServiceContainer.ResourceTypes.Distinct().Where(t => !t.Facets.IsOpenType)) { type.Facets.Add(NodeFacet.Attribute(new OpenTypeResourceAttribute(type, (rp => rp.IsNavigation || rp.PrimaryKey != null || rp.Facets.ConcurrencyModeFixed)))); } } #if !ClientSKUFramework w.AfterServiceCreation.Add(() => (w as NonClrWorkspace).OpenTypeMethodsImplementation = System.Data.Test.Astoria.LateBound.OpenTypeMethodsImplementations.Realistic); #endif // immediately after creating the service, register the undeclared properties' types w.AfterServiceCreation.Insert(0, () => RegisterTypesForUnDeclaredProperties(w)); }
protected override void WorkspaceCallback(Workspace workspace) { Microsoft.OData.Client.ODataProtocolVersion maxProtocolVersion = Microsoft.OData.Client.ODataProtocolVersion.V4; if (workspace.Settings.MaxProtocolVersion.HasValue) { maxProtocolVersion = workspace.Settings.MaxProtocolVersion.Value; } workspace.GenerateCallOrderInterceptors = true; // use custom concurrency provider for workspaces that can if (workspace.DataLayerProviderKind == DataLayerProviderKind.InMemoryLinq) { if (workspace.Settings.UpdatableImplementation == UpdatableImplementation.DataServiceUpdateProvider) { workspace.ServiceModifications.Interfaces.IServiceProvider.Services[typeof(Microsoft.OData.Service.Providers.IDataServiceUpdateProvider)] = "new UpdateProviderWrapper(this.CurrentDataSource)"; } else { workspace.ServiceModifications.Interfaces.IServiceProvider.Services[typeof(Microsoft.OData.Service.IUpdatable)] = "new UpdatableWrapper(this.CurrentDataSource)"; } } else if (workspace.DataLayerProviderKind == DataLayerProviderKind.NonClr) { workspace.Settings.UpdatableImplementation = UpdatableImplementation.DataServiceUpdateProvider; workspace.Settings.UseLazyPropertyLoading = false; // do this NOW instead of later, so that we can refer to these settings (workspace as NonClrWorkspace).DefineClrProperties(); if (AstoriaTestProperties.UseOpenTypes) { OpenTypesUtil.SetupDefaultOpenTypeAttributes(workspace); } } workspace.ServiceContainer.ResourceContainers.Remove("Invoices"); #region set up etags if (workspace.DataLayerProviderKind != DataLayerProviderKind.LinqToSql) { HashSet <ResourceType> typesWithETags = new HashSet <ResourceType>(); foreach (ResourceContainer container in workspace.ServiceContainer.ResourceContainers) { ResourceType baseType = container.BaseType; if (!typesWithETags.Add(baseType)) { continue; } // set up ETags NodeType[] etagTypes = new NodeType[] { Clr.Types.String, Clr.Types.Int16, Clr.Types.Int32, Clr.Types.Int64, Clr.Types.Guid }; List <ResourceProperty> possibleETagProperties = baseType.Properties.OfType <ResourceProperty>() .Where(p => etagTypes.Contains(p.Type) && !p.IsComplexType && !p.IsNavigation && p.PrimaryKey == null && p.Facets.IsDeclaredProperty && !p.Facets.FixedLength && p.ResourceType == baseType && p.Facets.UnderlyingType == UnderlyingType.Same && !p.Facets.IsStoreBlob && (p.Type != Clr.Types.String || (p.Facets.MaxSize.HasValue && p.Facets.MaxSize.Value < 512))) .ToList(); if (possibleETagProperties.Any()) { baseType.Facets.Add(NodeFacet.Attribute(new ConcurrencyAttribute(baseType, possibleETagProperties.Choose(2).Select(p => p.Name).ToArray()))); } } } #endregion #region set up blobs if (Versioning.Server.SupportsLiveFeatures && workspace.DataLayerProviderKind != DataLayerProviderKind.LinqToSql) { var edmWorkspace = workspace as EdmWorkspace; if (edmWorkspace != null) { edmWorkspace.CsdlCallbacks.Add(delegate(XmlDocument doc) { doc.InnerXml = doc.InnerXml.Replace(TestUtil.TestNamespaceManager.LookupNamespace("csdl"), TestUtil.TestNamespaceManager.LookupNamespace("csdl2")); }); edmWorkspace.SsdlCallbacks.Add(delegate(XmlDocument doc) { doc.InnerXml = doc.InnerXml.Replace("http://schemas.microsoft.com/ado/2006/04/edm/ssdl", "http://schemas.microsoft.com/ado/2009/02/edm/ssdl"); }); edmWorkspace.MslCallbacks.Add(delegate(XmlDocument doc) { doc.InnerXml = doc.InnerXml.Replace("urn:schemas-microsoft-com:windows:storage:mapping:CS", "http://schemas.microsoft.com/ado/2008/09/mapping/cs"); }); } foreach (ResourceContainer container in workspace.ServiceContainer.ResourceContainers.Where(rc => !(rc is ServiceOperation))) { if (workspace.DataLayerProviderKind == DataLayerProviderKind.Edm) { // After named-stream redesign, adding streams to EF is non-trivial continue; } if (container.ResourceTypes.Any(rt => rt.Facets.NamedStreams.Any())) { continue; } // because we don't represent streams as properties, having streams appear on anything other than the absolute base type // makes call order prediction very hard if (container.BaseType.BaseTypes.Any()) { continue; } var type = container.BaseType; switch (AstoriaTestProperties.Random.Next(3)) { case 0: type.Facets.Add(NodeFacet.Attribute(new NamedStreamResourceAttribute(type, "PhotoStream"))); break; case 1: type.Facets.Add(NodeFacet.Attribute(new NamedStreamResourceAttribute(type, "PhotoStream"))); type.Facets.Add(NodeFacet.Attribute(new NamedStreamResourceAttribute(type, "ThumbnailStream"))); type.Facets.Add(NodeFacet.Attribute(new NamedStreamResourceAttribute(type, "HighResolutionStream"))); break; } } } if (workspace.DataLayerProviderKind != DataLayerProviderKind.LinqToSql) { string streamProviderComparerTypeName = typeof(ReferenceEqualityComparer).FullName; if (workspace.DataLayerProviderKind == DataLayerProviderKind.Edm) { streamProviderComparerTypeName = workspace.Name + "EqualityComparer"; List <string> equalityComparerCode = new List <string>() { "public class " + streamProviderComparerTypeName + " : System.Data.Test.Astoria.KeyBasedEqualityComparerBase", "{", " protected override string[] GetKeyPropertyNames(Type entityType)", " {", " entityType = ObjectContext.GetObjectType(entityType);", " var fullTypeName = entityType.FullName;", }; foreach (var type in workspace.ServiceContainer.ResourceTypes) { equalityComparerCode.Add(string.Join(Environment.NewLine, new string[] { " if(fullTypeName == \"" + type.FullName + "\")", " {", " return new string[] { " + string.Join(", ", type.Properties.Where(p => p.PrimaryKey != null).Select(p => '"' + p.Name + '"').ToArray()) + " };", " }", })); } equalityComparerCode.Add(" throw new Exception(\"Unrecognized type\");"); equalityComparerCode.Add(" }"); equalityComparerCode.Add("}"); workspace.GlobalAdditionalCode += string.Join(Environment.NewLine, equalityComparerCode); } #region for inmemory/nonclr, make all int key properties server generated if (workspace.DataLayerProviderKind == DataLayerProviderKind.NonClr || workspace.DataLayerProviderKind == DataLayerProviderKind.InMemoryLinq) { foreach (ResourceType type in workspace.ServiceContainer.ResourceTypes) { foreach (NodeProperty property in type.Key.Properties) { if (property.Type == Clr.Types.Int32) { property.Facets.ServerGenerated = true; } } } } #endregion #region find possible blob types, and set up stream provider List <ResourceType> possibleBlobTypes = new List <ResourceType>(); foreach (ResourceType type in workspace.ServiceContainer.ResourceContainers.Where(rc => !(rc is ServiceOperation)).Select(rc => rc.BaseType)) { // need to find one that has only generated keys, all other propeties nullable, and no nav props if (type.Key.Properties.Any(p => !p.Facets.ServerGenerated)) { continue; } if (type.Properties.OfType <ResourceProperty>().Any(p => p.PrimaryKey == null && !p.IsNavigation && !p.Facets.Nullable)) { continue; } if (type.Properties.OfType <ResourceProperty>().Any(p => p.IsNavigation)) { continue; } possibleBlobTypes.Add(type); } if (possibleBlobTypes.Any()) { List <ResourceType> blobTypes = new List <ResourceType>(); // want one with etags, and one without ResourceType blobType = possibleBlobTypes.Where(rt => rt.Properties.Any(p => p.Facets.ConcurrencyModeFixed)).Choose(); if (blobType != null) { blobType.Facets.Add(NodeFacet.Attribute(new BlobsAttribute(blobType))); blobTypes.Add(blobType); } blobType = possibleBlobTypes.Where(rt => !rt.Properties.Any(p => p.Facets.ConcurrencyModeFixed)).Choose(); if (blobType != null) { blobType.Facets.Add(NodeFacet.Attribute(new BlobsAttribute(blobType))); blobTypes.Add(blobType); } workspace.ServiceModifications.Interfaces.IServiceProvider.Services[typeof(Microsoft.OData.Service.Providers.IDataServiceStreamProvider)] = "new StreamProviderWrapper(new System.Data.Test.Astoria.InMemoryStreamProvider<" + streamProviderComparerTypeName + ">())"; workspace.Settings.StreamProviderImplementation = StreamProviderImplementation.DataServiceStreamProvider; if (Versioning.Server.SupportsLiveFeatures && workspace.DataLayerProviderKind != DataLayerProviderKind.Edm) { workspace.ServiceModifications.Interfaces.IServiceProvider.Services[typeof(Microsoft.OData.Service.Providers.IDataServiceStreamProvider2)] = "new StreamProvider2Wrapper(new System.Data.Test.Astoria.InMemoryStreamProvider<" + streamProviderComparerTypeName + ">())"; workspace.Settings.StreamProviderImplementation = StreamProviderImplementation.DataServiceStreamProvider2; var blobTypesWithoutNamedStreams = blobTypes.Where(t => !t.Facets.NamedStreams.Any()).ToList(); if (blobTypesWithoutNamedStreams.Count != 0) { var blobTypeWithNamedStreams = blobTypesWithoutNamedStreams.Choose(); blobTypeWithNamedStreams.Facets.Add(NodeFacet.Attribute(new NamedStreamResourceAttribute(blobTypeWithNamedStreams, "Thumbnail"))); } } List <string> typeResolverLines = new List <string>(); foreach (ResourceType rt in blobTypes) { // safe because we know the types are disjoint (either do or do not have etags) and that they were the basetypes of their containers IEnumerable <ResourceContainer> containers = workspace.ServiceContainer.ResourceContainers.Where(rc => rc.BaseType == rt); foreach (ResourceContainer rc in containers) { typeResolverLines.Add(" if(entitySetName == \"" + rc.Name + "\")"); typeResolverLines.Add(" return \"" + rt.Namespace + "." + rt.Name + "\";"); } } typeResolverLines.Add(" return null;"); string typeResolverCode = string.Join(Environment.NewLine, typeResolverLines.ToArray()); workspace.RequiredFrameworkSources.Add("InMemoryStreamProvider.cs"); workspace.RequiredFrameworkSources.Add("KeyBasedEqualityComparerBase.cs"); workspace.RequiredFrameworkSources.Add("ReferenceEqualityComparer.cs"); var streamProviderFile = new ConstructedFile("InMemoryStreamProvider.cs"); workspace.ServiceModifications.Files.Add(streamProviderFile); streamProviderFile.AddMethod("ResolveType", new NewMethodInfo() { MethodSignature = "string ResolveType(string entitySetName, DataServiceOperationContext operationContext)", BodyText = typeResolverCode, }); } #endregion } #endregion #region set up service operations List <ServiceOperation> serviceOperations = new List <ServiceOperation>(); foreach (ResourceContainer container in workspace.ServiceContainer.ResourceContainers) { // no MEST yet for service ops!! if (!workspace.ServiceContainer.ResourceContainers.Any(c => c != container && c.BaseType == container.BaseType)) { foreach (RequestVerb verb in new RequestVerb[] { RequestVerb.Get, RequestVerb.Post }) { ServiceOperation serviceOp = Resource.ServiceOperation(verb.ToString() + "_" + container.Name, container, container.BaseType, container.ResourceTypes.ToArray()); serviceOp.Verb = verb; string fullTypeName = container.BaseType.Namespace + "." + container.BaseType.Name; if (workspace.DataLayerProviderKind == DataLayerProviderKind.NonClr && !container.BaseType.Facets.IsClrType) { fullTypeName = typeof(NonClr.RowEntityType).FullName; } serviceOp.ServiceOpCode = string.Join(Environment.NewLine, new string[] { (verb == RequestVerb.Get ? "[WebGet]" : "[WebInvoke(Method = \"POST\")]"), "public IQueryable<" + fullTypeName + "> " + serviceOp.Name + "()", "{", " return GetEntitySet<" + fullTypeName + ">(\"" + container.Name + "\");", "}" }); serviceOp.ServiceOperationResultKind = Microsoft.OData.Service.Providers.ServiceOperationResultKind.QueryWithMultipleResults; serviceOp.ExpectedTypeName = fullTypeName; serviceOperations.Add(serviceOp); } } } workspace.ServiceContainer.AddNodes(serviceOperations); workspace.AddServiceOperationCode(); #endregion }
public static NodeFacet ConcurrencyModeFixed() { return(NodeFacet.ConcurrencyMode(System.Data.Test.Astoria.ConcurrencyMode.Fixed)); }
private void MakeMLE(Workspace w, string typeName) { ResourceType type = w.ServiceContainer.ResourceTypes.Where(p => p.Name == typeName).First(); type.Facets.Add(NodeFacet.Attribute(new BlobsAttribute(type))); }
protected override void WorkspaceCallback(Workspace workspace) { if (workspace.DataLayerProviderKind == DataLayerProviderKind.NonClr) { #if !ClientSKUFramework // do this NOW instead of later, so that we can refer to these settings (workspace as NonClrWorkspace).DefineClrProperties(); #endif } Dictionary <string, string[]> tokensMap = new Dictionary <string, string[]>(); tokensMap.Add("DefectBug", new string[] { "Number" }); tokensMap.Add("Owner", new string[] { "LastName" }); tokensMap.Add("Run", new string[] { "Purpose" }); tokensMap.Add("Task", new string[] { "Deleted", "Investigates" }); tokensMap.Add("OwnerDetail", new string[] { "Level" }); tokensMap.Add("ProjectBug", new string[] { "Number" }); tokensMap.Add("NonDefaultMappings", new string[] { "c_int_AS_decimal", "c_smallint_AS_decimal", "c_smalldatetime_AS_datetime" }); tokensMap.Add("AllTypes", new string[] { "c2_int", "c3_smallint", "c4_tinyint", "c5_bit", "c6_datetime", "c7_smalldatetime", "c8_decimal_28_4_", "c9_numeric_28_4_", "c10_real", "c11_float", "c12_money", "c13_smallmoney", /*"c14_varchar_512_", "c15_char_512_",*/ "c26_smallint", "c27_tinyint", "c28_bit", "c46_uniqueidentifier", "c47_bigint" }); tokensMap.Add("Vehicle", new string[] { "Make", "Model", "Year" }); tokensMap.Add("Test1s", new string[] { "Name" }); // for deep expand where top type has no etag tokensMap.Add("Run2s", new string[] { "Name" }); tokensMap.Add("Student", new string[] { "FirstName", "MiddleName", "LastName", "Major" }); tokensMap.Add("College", new string[] { "Name", "City", "State" }); tokensMap.Add("Config", new string[] { "Arch" }); //tokensMap.Add("DeepTree_C", new string[] { "C_Int" }); tokensMap.Add("LabOwners", new string[] { "Changed" }); foreach (ResourceType type in workspace.ServiceContainer.ResourceTypes.Where(rt => rt.Name.StartsWith("DataKey_"))) { tokensMap.Add(type.Name, type.Properties .OfType <ResourceProperty>() .Where(p => p.PrimaryKey == null && !p.IsNavigation && !p.IsComplexType) .Select(p => p.Name) .ToArray()); } foreach (KeyValuePair <string, string[]> pair in tokensMap) { ResourceType type = workspace.ServiceContainer.ResourceTypes.SingleOrDefault(t => t.Name == pair.Key); if (type == null) { // look through the basetypes type = workspace.ServiceContainer.ResourceTypes.SingleOrDefault(t => t.BaseType != null && t.BaseType.Name == pair.Key); if (type == null) { AstoriaTestLog.FailAndContinue(new TestWarningException("Could not find type '" + pair.Key + "'")); continue; } type = type.BaseType as ResourceType; } // ensure that we put the property names in the order they are in the service container List <string> propertyNames = new List <string>(); List <string> etagProperties = pair.Value.ToList(); foreach (var property in type.Properties.OfType <ResourceProperty>()) { var propertyName = property.Name; if (etagProperties.Contains(propertyName)) { propertyNames.Add(propertyName); etagProperties.Remove(propertyName); if (workspace.DataLayerProviderKind == DataLayerProviderKind.NonClr && !property.Facets.Nullable) { // due to an issue with the provider not enforcing non-nullability on weakly-backed properties, // if the property is non-nullable make sure its strongly backed property.Facets.IsClrProperty = true; type.Facets.IsClrType = true; foreach (var derived in type.DerivedTypes) { derived.Facets.IsClrType = true; } } } } if (etagProperties.Any()) { throw new TestWarningException(string.Format("Could not find properties on type '{0}': {1}", type.Name, string.Join(", ", etagProperties.ToArray()))); } type.Facets.Add(NodeFacet.Attribute(new ConcurrencyAttribute(type, propertyNames))); } List <ServiceOperation> serviceOperations = new List <ServiceOperation>(); foreach (ResourceContainer container in workspace.ServiceContainer.ResourceContainers) { // no MEST yet for service ops!! if (workspace.ServiceContainer.ResourceContainers.Any(c => c != container && c.BaseType == container.BaseType)) { continue; } ServiceOperation serviceOp = Resource.ServiceOperation("Get" + container.Name, container, container.BaseType, container.ResourceTypes.ToArray()); string fullTypeName = container.BaseType.Namespace + "." + container.BaseType.Name; #if !ClientSKUFramework if (workspace.DataLayerProviderKind == DataLayerProviderKind.NonClr && !container.BaseType.Facets.IsClrType) { fullTypeName = typeof(NonClr.RowEntityType).FullName; } #endif serviceOp.ServiceOpCode = string.Join(Environment.NewLine, new string[] { "[WebGet]", "public IQueryable<" + fullTypeName + "> " + serviceOp.Name + "()", "{", " return GetEntitySet<" + fullTypeName + ">(\"" + container.Name + "\");", "}" }); #if !ClientSKUFramework serviceOp.ServiceOperationResultKind = Microsoft.OData.Service.Providers.ServiceOperationResultKind.QueryWithMultipleResults; #endif serviceOp.ExpectedTypeName = fullTypeName; serviceOperations.Add(serviceOp); } workspace.ServiceContainer.AddNodes(serviceOperations); workspace.AddServiceOperationCode(); }