Ejemplo n.º 1
0
        //---------------------------------------------------------------------
        // 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())));
                }
            }
        }
Ejemplo n.º 2
0
        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)));
        }
Ejemplo n.º 3
0
 //---------------------------------------------------------------------
 // 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)));
     }
 }
Ejemplo n.º 4
0
        // 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);
        }
Ejemplo n.º 5
0
        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)));
                }
            }
        }
Ejemplo n.º 6
0
        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));
        }
Ejemplo n.º 7
0
        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
        }
Ejemplo n.º 8
0
        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)));
        }
Ejemplo n.º 9
0
        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();
        }