private bool CreateKeyedResourceInstance(ResourceContainer container, ResourceType resourceType, out KeyExpression key, out KeyedResourceInstance newResource) { int retryCount = 5; if (!_existingKeyMap.Keys.Contains(container)) { _existingKeyMap.Add(container, new KeyExpressions()); } newResource = resourceType.CreateRandomResource(container, new KeyExpressions(), false); // should not make request key = newResource.ResourceInstanceKey.CreateKeyExpression(container, resourceType); while (_existingKeyMap[container].Contains(key) && retryCount > 0) { newResource.ResourceInstanceKey = ResourceInstanceUtil.CreateUniqueKey(container, resourceType, new KeyExpressions(), new KeyExpressions()); key = newResource.ResourceInstanceKey.CreateKeyExpression(container, resourceType); retryCount--; } if (retryCount == 0) { newResource = null; key = null; return(false); } _existingKeyMap[container].Add(key); _existingEntityMap[key] = newResource; return(true); }
/// <summary> /// Implements IDataInserter.AddEntity by generating a IUpdatable.CreateResource call and multiple IUpdatable.SetValue calls /// </summary> /// <param name="key">Key expression for new entity</param> /// <param name="entity">Update tree for new entity</param> public void AddEntity(KeyExpression key, KeyedResourceInstance entity) { // generate a variable name for this entity and save it // int entityID = entityIDs.Count; entityIDs[entity] = entityID; string entityObjectName = "entity" + entityID; // code-gen the CreateResource and SetValue calls // code.AppendLine("//Adding entity"); foreach (string line in WriteObject(entityObjectName, entity)) { code.AppendLine(line); } code.AppendLine(entityListName + ".Add(" + entityObjectName + ");"); code.AppendLine(string.Empty); // Fire the event // if (this.OnAddingEntity != null) { OnAddingEntity(key, entity); } // ensure that a later Flush/Close will write the SaveChanges call changesSaved = false; }
/// <summary> /// Implements IDataInserter.AddAssociation by generating the appropriate IUpdatable.AddReferenceToCollection or IUpdatable.SetReference call /// </summary> /// <param name="parent">Update tree of parent, must have already been added using AddEntity</param> /// <param name="property">Navigation property for the association</param> /// <param name="child">Update tree of child, must have already been added using AddEntity</param> public void AddAssociation(KeyedResourceInstance parent, ResourceProperty property, KeyedResourceInstance child) { // look up the object names for these entities // string parentObjectName = entityListName + "[" + entityIDs[parent] + "]"; string childObjectName = entityListName + "[" + entityIDs[child] + "]"; // code-gen the appropriate IUpdatable call // code.AppendLine("//Adding association"); if (property.OtherAssociationEnd.Multiplicity == Multiplicity.Many) { code.AppendLine("updatable.AddReferenceToCollection(" + parentObjectName + ", \"" + property.Name + "\", " + childObjectName + ");"); } else { code.AppendLine("updatable.SetReference(" + parentObjectName + ", \"" + property.Name + "\", " + childObjectName + ");"); } code.AppendLine(); // Fire the event // if (this.OnAddingAssociation != null) { OnAddingAssociation(parent, property, child); } // ensure that a later Flush/Close will write the SaveChanges call changesSaved = false; }
public override KeyedResourceInstance GetSingleResourceByKey(KeyExpression keyExpression) { if (keyExpression.Properties.OfType <ResourceProperty>().Where(rp => rp.Type.ClrType.Equals(typeof(DateTime))).Count() > 0) { UriQueryBuilder uriQueryBuilder = new UriQueryBuilder(this, this.ServiceUri); _workaroundDateTimeQuery = uriQueryBuilder.Build(Query.From( Exp.Variable(keyExpression.ResourceContainer)) .Where(keyExpression) .Select()); } KeyedResourceInstance o = null; try { o = SocketExceptionHandler.Execute <KeyedResourceInstance>( () => GetSingleResourceByKeyBase(keyExpression)); } catch (Microsoft.OData.Client.DataServiceQueryException exc) { if (exc.Response.StatusCode != 404) { throw exc; } // if DSV is not present, its not an Astoria-level error if (!exc.Response.Headers.ContainsKey("OData-Version")) { throw exc; } } return(o); }
/// <summary> /// Implements IDataInserter.AddEntity by creating a POST-based insert request and adding it to the batch queue /// </summary> /// <param name="key">Key expression for new entity</param> /// <param name="entity">Update tree for new entity</param> public void AddEntity(KeyExpression key, KeyedResourceInstance entity) { // build the request // ExpNode containerQuery = ContainmentUtil.BuildCanonicalQuery(key, true); AstoriaRequest request = workspace.CreateRequest(containerQuery, entity, RequestVerb.Post); // set ETagHeaderExpected appropriately if (key.ResourceType.Properties.Any(p => p.Facets.ConcurrencyModeFixed)) { request.ETagHeaderExpected = true; } // add it to the queue // queue.Add(request); // store the content-id // contentIDMap[entity] = request.Headers["Content-ID"]; // fire the event // if (this.OnAddingEntity != null) { OnAddingEntity(key, entity); } }
private XmlElement CreateIdElement(KeyedResourceInstance keyedResourceInstance) { XmlElement idNode = CreateAtomElement("id"); idNode.InnerText = CreateCanonicalUri(keyedResourceInstance.ResourceInstanceKey); return(idNode); }
private XmlElement CreateBasicEntryElement(KeyedResourceInstance keyedResourceInstance, XmlNode parentNode) { XmlElement entryElement = CreateAtomElement("entry"); if (parentNode == null) { AddNamespacesToTopElement(entryElement); document.AppendChild(entryElement); } else { parentNode.AppendChild(entryElement); } //add type attribute if (keyedResourceInstance.IncludeTypeMetadataHint) { string typeName = null; //if( this.Workspace.DataLayerProviderKind == DataLayerProviderKind.NonClr ) // typeName = keyedResourceInstance.ResourceTypeName; //else typeName = this.Workspace.ContextNamespace + "." + keyedResourceInstance.TypeName; XmlElement typeElement = CreateAtomElement("category"); typeElement.SetAttribute("scheme", DataWebSchemeNamespace); typeElement.SetAttribute("term", typeName); entryElement.AppendChild(typeElement); } return(entryElement); }
public AstoriaRequest MakeMergeRequest(AstoriaRequest request, KeyedResourceInstance resourceInstance) { request.Verb = RequestVerb.Patch; request.ContentType = "application/atom+xml"; request.UpdateTree = resourceInstance; return(request); }
protected void Visit(ExpNode caller, ExpNode node, XmlElement parentNode) { nodeStack.Push(node); if (node == null) { throw new ArgumentNullException("node"); } if (node is KeyedResourceInstance && (!(node is AssociationResourceInstance))) { KeyedResourceInstance e = (KeyedResourceInstance)node; CreateEntryElement(e, parentNode); } else if (node is AssociationResourceInstance) { AssociationResourceInstance e = (AssociationResourceInstance)node; if (caller == null) { CreateLinkPayload(e, parentNode); } else { CreateBinding(e, parentNode); } } //Below are two special cases else if (caller == null && node is ResourceInstanceSimpleProperty) { this.VisitResourceInstanceSimpleProperty(node as ResourceInstanceSimpleProperty, parentNode); } else if (caller == null && node is ResourceInstanceComplexProperty) { this.VisitResourceInstanceComplexProperty(node as ResourceInstanceComplexProperty, parentNode); } else if (caller == null && node is ResourceInstanceNavRefProperty) { ResourceInstanceNavRefProperty navRef = node as ResourceInstanceNavRefProperty; AssociationResourceInstance associationResourceInstance = navRef.TreeNode as AssociationResourceInstance; if (associationResourceInstance != null && associationResourceInstance.Operation == AssociationOperation.Remove) { this.CreateUnBinding(parentNode); } else { throw new Exception("Unknown node type:" + navRef.TreeNode.GetType()); } } else if (caller == null && node is ResourceInstanceCollection) { ResourceInstanceCollection collection = node as ResourceInstanceCollection; CreateLinksElement(collection, null); } else { throw new Exception("Unknown node type: " + node.GetType()); } nodeStack.Pop(); }
private string GetResourceType(KeyedResourceInstance e) { string resourceType = e.ResourceSetName; if (resourceType == null) { resourceType = e.ResourceInstanceKey.ResourceSetName; } return(resourceType); }
internal static KeyedResourceInstance CreateKeyedResourceInstanceByExactClone(ResourceContainer container, ResourceType resourceType, object dataObject) { List <ResourceInstanceProperty> properties = new List <ResourceInstanceProperty>(); List <ResourceInstanceProperty> keyProperties = new List <ResourceInstanceProperty>(); properties.AddRange(CloneObjectToResourceInstanceProperties(resourceType.Properties.OfType <ResourceProperty>().Where(rp => rp.PrimaryKey == null && rp.IsNavigation == false), dataObject)); keyProperties.AddRange(CloneObjectToResourceInstanceProperties(resourceType.Properties.OfType <ResourceProperty>().Where(rp => rp.PrimaryKey != null && rp.IsNavigation == false), dataObject)); ResourceInstanceKey key = new ResourceInstanceKey(container, resourceType, keyProperties.ToArray()); KeyedResourceInstance keyResourceInstance = new KeyedResourceInstance(key, properties.ToArray()); return(keyResourceInstance); }
public static KeyedResourceInstance CreateKeyedResourceInstanceByClone(ResourceContainer container, ResourceType resourceType, bool excludeRelationships) { Workspace workspace = container.Workspace; //Clone for an existing resource, and update its key KeyExpression keyExpression = workspace.GetRandomExistingKey(container, resourceType); if (keyExpression == null) { return(null); } KeyedResourceInstance dataObject = workspace.GetSingleResourceByKey(keyExpression); if (dataObject == null) { return(null); } ResourceInstanceKey key = null; // if there are any non-server-generated key properties, then we need to build the key if (keyExpression.ResourceType.Properties.Any(p => p.PrimaryKey != null && !p.Facets.ServerGenerated)) { ResourceType newResourceType = container.ResourceTypes.Where(rt => rt.Name == dataObject.TypeName).FirstOrDefault(); key = CreateUniqueKey(container, newResourceType); } //Foreach property in dataObject create a ResourceProperty List <ResourceInstanceProperty> properties = new List <ResourceInstanceProperty>(); properties.AddRange(dataObject.Properties.OfType <ResourceInstanceSimpleProperty>().ToArray()); properties.AddRange(dataObject.Properties.OfType <ResourceInstanceComplexProperty>().ToArray()); if (!excludeRelationships) { properties.AddRange(CloneRequiredRelationships(container, keyExpression.ResourceType, keyExpression)); } KeyedResourceInstance keyResourceInstance = null; if (key != null) { keyResourceInstance = new KeyedResourceInstance(key, properties.ToArray()); } else { keyResourceInstance = new KeyedResourceInstance(dataObject.ResourceSetName, dataObject.TypeName, properties.ToArray()); } return(keyResourceInstance); }
public static AstoriaRequest BuildInsert(Workspace workspace, ResourceContainer container, ResourceType type, HttpStatusCode expectedStatusCode, SerializationFormatKind format, out KeyExpression createdKey) { KeyedResourceInstance newResource = type.CreateRandomResource(container); if (newResource == null) { newResource = ResourceInstanceUtil.CreateKeyedResourceInstanceByClone(container, type); if (newResource == null) { createdKey = null; return(null); } } QueryNode query; if (!type.Key.Properties.Any(p => p.Facets.ServerGenerated) && newResource.ResourceInstanceKey != null) { createdKey = newResource.ResourceInstanceKey.CreateKeyExpression(container, type); query = ContainmentUtil.BuildCanonicalQuery(createdKey, true); } else { createdKey = null; // the key is unknown, must be server generated // in this case, lets hope that containment is a non-issue query = Query.From(Exp.Variable(container)) .Select(); if (!container.Facets.TopLevelAccess && expectedStatusCode == HttpStatusCode.Created) { expectedStatusCode = HttpStatusCode.BadRequest; } } AstoriaRequest request = workspace.CreateRequest(); request.Verb = RequestVerb.Post; request.Query = query; request.UpdateTree = newResource; request.ExpectedStatusCode = expectedStatusCode; request.Format = format; return(request); }
/// <summary> /// Implements IDataInserter.AddAssociation by creating a PUT/POST $ref request using cross-referencing, and adds it to the batch /// </summary> /// <param name="parent">Update tree of parent, must have already been added using AddEntity</param> /// <param name="property">Navigation property for the association</param> /// <param name="child">Update tree of child, must have already been added using AddEntity</param> public void AddAssociation(KeyedResourceInstance parent, ResourceProperty property, KeyedResourceInstance child) { // determine which verb to use // RequestVerb verb; if (property.OtherAssociationEnd.Multiplicity == Multiplicity.Many) { verb = RequestVerb.Post; } else { verb = RequestVerb.Put; } // create the request // AstoriaRequest request = workspace.CreateRequest(); request.Verb = verb; // use content-id cross referencing to link them // string parentContentId = contentIDMap[parent]; string childContentId = contentIDMap[child]; request.URI = "$" + parentContentId + "/" + property.Name + "/$ref"; request.Payload = "<adsm:uri xmlns:adsm=\"http://docs.oasis-open.org/odata/ns/metadata\">$" + childContentId + "</adsm:uri>"; // add it to the queue // queue.Add(request); // fire the event // if (this.OnAddingAssociation != null) { OnAddingAssociation(parent, property, child); } }
internal static ResourceInstanceKey CreateUniqueKey(ResourceContainer container, ResourceType resType, KeyExpressions relatedForeignKeys, KeyExpressions existingKeys) { KeyExpressions possibleRelatedForeignKeys = new KeyExpressions(); Workspace workspace = container.Workspace; int keysGenerated = 0; bool keyTrying = true; ResourceInstanceKey resourceInstanceKey = null; do { possibleRelatedForeignKeys = new KeyExpressions(); resourceInstanceKey = TryCreateUniqueResourceInstanceKey(container, resType, possibleRelatedForeignKeys); KeyExpression keyExpression = resourceInstanceKey.CreateKeyExpression(container, resType); // need to make sure its not a duplicate // if (existingKeys == null) { KeyedResourceInstance o = workspace.GetSingleResourceByKey(keyExpression); if (o == null) { keyTrying = false; } } else { keyTrying = existingKeys.Contains(keyExpression); } keysGenerated++; if (keysGenerated > 25) { throw new Microsoft.Test.ModuleCore.TestFailedException("Unable to create a unique key"); } }while (keyTrying); relatedForeignKeys.Add(possibleRelatedForeignKeys); return(resourceInstanceKey); }
public static AstoriaRequest BuildUpdate(Workspace workspace, KeyExpression modifiedKey, bool replace, HttpStatusCode expectedStatusCode, SerializationFormatKind format) { if (modifiedKey == null) { return(null); } ResourceContainer container = modifiedKey.ResourceContainer; ResourceType resourceType = modifiedKey.ResourceType; if (replace && resourceType.Properties.Any(p => p.Facets.IsIdentity)) { return(null); } string keyString = UriQueryBuilder.CreateKeyString(modifiedKey, false); if (expectedStatusCode == HttpStatusCode.NoContent && (keyString.Contains("/") || keyString.Contains(Uri.EscapeDataString("/")))) { expectedStatusCode = HttpStatusCode.BadRequest; } QueryNode query = ContainmentUtil.BuildCanonicalQuery(modifiedKey); List <ResourceInstanceProperty> properties = new List <ResourceInstanceProperty>(); string[] propertiesToSkip; //Skip because setting the birthdate to a random Datetime won't work due to contraints //if (resourceType.Name == "Employees") // propertiesToSkip = new string[] { "BirthDate" }; ////Skipping because it has some weird constraint on it //else if (resourceType.Name == "Order_Details") // propertiesToSkip = new string[] { "Discount" }; //else // propertiesToSkip = new string[] { }; foreach (ResourceProperty resourceProperty in resourceType.Properties.OfType <ResourceProperty>() .Where(p => !p.IsNavigation && p.PrimaryKey == null && !p.Facets.IsIdentity)) //&& !p.IsComplexType //&& !propertiesToSkip.Contains(p.Name))) { properties.Add(resourceProperty.CreateRandomResourceInstanceProperty()); } if (!properties.Any()) { return(null); } KeyedResourceInstance resourceInstance = new KeyedResourceInstance( ResourceInstanceKey.ConstructResourceInstanceKey(modifiedKey), properties.ToArray()); AstoriaRequest request = workspace.CreateRequest(); request.Verb = replace ? RequestVerb.Put : RequestVerb.Patch; request.Query = query; request.UpdateTree = resourceInstance; request.ExpectedStatusCode = expectedStatusCode; request.Format = format; if (modifiedKey.ResourceType.Properties.Any(p => p.Facets.ConcurrencyModeFixed)) { request.Headers[ConcurrencyUtil.IfMatchHeader] = modifiedKey.ETag; request.ETagHeaderExpected = true; } return(request); }
protected virtual string Visit(ExpNode caller, ExpNode node) { if (node == null) { throw new ArgumentNullException("node"); } if (node is KeyedResourceInstance && (!(node is AssociationResourceInstance))) { KeyedResourceInstance e = (KeyedResourceInstance)node; _resourceType = this.GetResourceType(e); _typeStack.Push(_resourceType); string properties = null; if (this.RequestVerb == RequestVerb.Post && e.ResourceInstanceKey != null) { foreach (ResourceInstanceProperty resourceProperty in e.ResourceInstanceKey.KeyProperties) { if (properties != null) { properties += "," + this.Visit(e, resourceProperty); } else { properties = this.Visit(e, resourceProperty); } } } foreach (ResourceInstanceProperty resourceProperty in e.Properties) { if (properties != null) { properties += "," + this.Visit(e, resourceProperty); } else { properties = this.Visit(e, resourceProperty); } } _resourceType = _typeStack.Pop(); string typeAttribute = null; //if( Workspace.DataLayerProviderKind == DataLayerProviderKind.NonClr ) // typeAttribute = String.Format("type:\"{0}\" ", e.ResourceTypeName); //else typeAttribute = String.Format("type:\"{0}.{1}\" ", this.Workspace.ContextNamespace, e.TypeName); string uriAttribute = null; string metadataString = null; if (e.ResourceInstanceKey != null && this.RequestVerb != RequestVerb.Post) { uriAttribute = String.Format("uri:\"{0}\"", CreateCanonicalUri(e.ResourceInstanceKey)); } if (uriAttribute != null) { if (e.IncludeTypeMetadataHint) { metadataString = String.Format("__metadata: {{ {0}, {1}}}", typeAttribute, uriAttribute); } else { metadataString = String.Format("__metadata: {{ {0} }}", uriAttribute); } } else { if (e.IncludeTypeMetadataHint) { metadataString = String.Format("__metadata: {{ {0} }}", typeAttribute); } } //if (uriAttribute != null && e.IncludeTypeMetadataHint) // metadataString = String.Format("__metadata: {{ {0}, {1}}}", typeAttribute, uriAttribute); //else if (e.IncludeTypeMetadataHint && uriAttribute == null) // metadataString = String.Format("__metadata: {{ {0} }}", typeAttribute); string payload = null; if (properties == null) { payload = ApplyErrors(node, String.Format("{{{0}}}", metadataString)); } else if (metadataString != null) { payload = ApplyErrors(node, String.Format("{{{0}, {1}}}", metadataString, properties)); } else { payload = ApplyErrors(node, String.Format("{{{0}}}", properties)); } return(payload); } else if (node is AssociationResourceInstance) { AssociationResourceInstance e = (AssociationResourceInstance)node; if (e.Operation == AssociationOperation.Add) { string uri = CreateCanonicalUri(e.ResourceInstanceKey); string payload = null; if (caller == null) { payload = "{ uri:\"" + uri + "\"}"; } else if (e.IncludeTypeInBind) { payload = String.Format("__metadata: {{ uri:\"{0}\", type:\"{1}.{2}\"}}", uri, this.Workspace.ContextNamespace, e.ResourceInstanceKey.ResourceTypeName); } else { payload = String.Format("__metadata: {{ uri:\"{0}\"}}", uri); } return(ApplyErrors(node, payload)); } else { string navString = null; if (caller != null) { navString = e.Name + ": null"; } else { navString = "{ uri: null }"; } return(ApplyErrors(node, navString)); } } /* * else if (node is ResourceInstanceKey) * { * ResourceInstanceKey e = (ResourceInstanceKey)node; * if (RequestVerb == RequestVerb.Post) * { * string payload = String.Format("__metadata: {{ type:\"{0}.{1}\" }}", this.Workspace.ContextNamespace, e.ResourceTypeName); * if (e.KeyProperties != null) * { * foreach (ResourceInstanceProperty resourceProperty in e.KeyProperties) * { * payload += String.Format(", {0}", this.Visit(e, resourceProperty)); * } * } * return ApplyErrors(node, payload); * } * else if (RequestVerb == RequestVerb.Put) * { * string keyValues = WriteCommaDelimitedKeyValues(e); * * string payloadUri = String.Format("/{0}({1})", e.ResourceSetName, keyValues); * return ApplyErrors(node, String.Format("__metadata: {{uri:\"{0}\" }}", payloadUri)); * } * throw new ArgumentException("Request Verb is incorrect can't build an update payload:" + this.RequestVerb.ToString()); * }*/ else if (node is ResourceInstanceSimpleProperty) { ResourceInstanceSimpleProperty e = (ResourceInstanceSimpleProperty)node; Type clrType = e.ClrType; object val = e.PropertyValue; if (val != null) { clrType = val.GetType(); } if (e.CreateDollarValue) { if (val == null) { return(null); } else if (clrType == typeof(byte[])) { return((new System.Text.UTF8Encoding()).GetString((byte[])val)); } else { return(AstoriaUnitTests.Data.TypeData.XmlValueFromObject(val)); } } string jsonStringValue; if (clrType == typeof(DateTime) && val is DateTime) { if (e.UseTickCountForJsonDateTime) { jsonStringValue = "'" + JsonPrimitiveTypesUtil.GetJsonDateTimeStringValue((DateTime)val) + "'"; } else { jsonStringValue = JsonPrimitiveTypesUtil.DateTimeToString(val); } } else { jsonStringValue = JsonPrimitiveTypesUtil.PrimitiveToString(val, clrType); if (clrType == typeof(double) || clrType == typeof(float)) { // PrimitiveToString will lose the trailing .0 if its a whole number long temp; if (long.TryParse(jsonStringValue, out temp)) { jsonStringValue += ".0"; } } } if (caller == null) { return("{" + ApplyErrors(node, String.Format("{0}: {1}", e.Name, jsonStringValue)) + "}"); } else { return(ApplyErrors(node, String.Format("{0}: {1}", e.Name, jsonStringValue))); } } else if (node is ResourceInstanceComplexProperty) { ResourceInstanceComplexProperty e = (ResourceInstanceComplexProperty)node; string properties = null; if (e.IncludeTypeMetadataHint) { properties += String.Format("__metadata: {{ type:\"{0}.{1}\" }}", this.Workspace.ContextNamespace, e.TypeName); } foreach (ResourceInstanceProperty resourceProperty in e.ComplexResourceInstance.Properties) { if (string.IsNullOrEmpty(properties)) { properties += this.Visit(e, resourceProperty); } else { properties += "," + this.Visit(e, resourceProperty); } } string results = null; if (caller == null) { results = "{" + e.Name + ": {" + properties + "}" + "}"; } else { results = e.Name + ": {" + properties + "}"; } return(ApplyErrors(node, results)); } else if (node is ResourceInstanceNavRefProperty) { ResourceInstanceNavRefProperty e = (ResourceInstanceNavRefProperty)node; AssociationResourceInstance associationResourceInstance = e.TreeNode as AssociationResourceInstance; string navString = null; if ((associationResourceInstance != null && associationResourceInstance.Operation != AssociationOperation.Remove)) { navString = e.Name + ": {"; navString += this.Visit(e, e.TreeNode); navString += "}"; } else if (associationResourceInstance != null && associationResourceInstance.Operation == AssociationOperation.Remove) { if (caller != null) { navString = e.Name + ": null"; } else { navString = "null"; } } else { navString = e.Name + ": "; navString += this.Visit(e, e.TreeNode); } return(ApplyErrors(node, navString)); } else if (node is ResourceInstanceNavColProperty) { ResourceInstanceNavColProperty e = (ResourceInstanceNavColProperty)node; //string navString = String.Format("{0}: {", e.Name); string navString = e.Name + ": ["; foreach (NamedNode namedNode in e.Collection.NodeList) { if (!(namedNode is AssociationResourceInstance)) { navString += this.Visit(e, namedNode) + ","; } else { navString += "{" + this.Visit(e, namedNode) + "},"; } } navString = navString.TrimEnd(','); navString += "]"; return(ApplyErrors(node, navString)); } else { throw new Exception("Unknown node type: " + node.GetType()); } }
private void CreateEntryElement(KeyedResourceInstance keyedResourceInstance, XmlNode parentNode) { currentResource = keyedResourceInstance; XmlElement entryElement = CreateBasicEntryElement(keyedResourceInstance, parentNode); //string relativeParentKey = null; //Add the Id if there is one if (this.RequestVerb != RequestVerb.Post) { if (keyedResourceInstance.ResourceInstanceKey != null) { XmlElement idNode = CreateIdElement(keyedResourceInstance); entryElement.AppendChild(idNode); } } ResourceType type = Workspace.ServiceContainer.ResourceTypes.Single(rt => rt.Name == keyedResourceInstance.TypeName); XmlElement propertiesNode = CreateDataWebMetadataElement("properties"); IEnumerable <ResourceInstanceProperty> properties = keyedResourceInstance.Properties; if (this.RequestVerb == RequestVerb.Post && keyedResourceInstance.ResourceInstanceKey != null) { properties = keyedResourceInstance.ResourceInstanceKey.KeyProperties.Union(properties); } foreach (ResourceInstanceProperty property in properties) { if (property is ResourceInstanceSimpleProperty) { ResourceInstanceSimpleProperty simpleResourceProperty = property as ResourceInstanceSimpleProperty; VisitResourceInstanceSimpleProperty(simpleResourceProperty, propertiesNode); } else if (property is ResourceInstanceComplexProperty) { ResourceInstanceComplexProperty complexResourceProperty = property as ResourceInstanceComplexProperty; if (complexResourceProperty.ComplexResourceInstance == null) { VisitResourceInstanceComplexProperty(complexResourceProperty, propertiesNode); } else { VisitResourceInstanceComplexProperty(complexResourceProperty, propertiesNode); } } else if (property is ResourceInstanceNavProperty) { ResourceInstanceNavProperty navigationProperty = property as ResourceInstanceNavProperty; VisitResourceNavigationProperty(navigationProperty, entryElement); } } if (propertiesNode.ChildNodes.Count > 0) { if (!type.Facets.HasStream) { XmlElement contentNode = CreateAtomElement("content"); XmlAttribute contentTypeAttribute = CreateAtomAttribute("type"); contentTypeAttribute.Value = RequestUtil.RandomizeContentTypeCapitalization("application/xml"); contentNode.Attributes.Append(contentTypeAttribute); contentNode.AppendChild(propertiesNode); entryElement.AppendChild(contentNode); } else { entryElement.AppendChild(propertiesNode); } } if (EntryElementCallback != null) { EntryElementCallback(entryElement); } }