// <summary> // Performs projection for a single row. Evaluates each projection argument against the specified // row, returning a result with the specified type. // </summary> // <param name="node"> Projection expression. </param> // <param name="row"> Row to project. </param> // <param name="resultType"> Type of the projected row. </param> // <returns> Projected row. </returns> private static PropagatorResult Project(DbProjectExpression node, PropagatorResult row, TypeUsage resultType) { DebugCheck.NotNull(node); DebugCheck.NotNull(node.Projection); var projection = node.Projection as DbNewInstanceExpression; if (null == projection) { throw new NotSupportedException(Strings.Update_UnsupportedProjection(node.Projection.ExpressionKind)); } // Initialize empty structure containing space for every element of the projection. var projectedValues = new PropagatorResult[projection.Arguments.Count]; // Extract value from the input row for every projection argument requested. for (var ordinal = 0; ordinal < projectedValues.Length; ordinal++) { projectedValues[ordinal] = Evaluator.Evaluate(projection.Arguments[ordinal], row); } // Return a new row containing projected values. var projectedRow = PropagatorResult.CreateStructuralValue(projectedValues, (StructuralType)resultType.EdmType, false); return(projectedRow); }
// <summary> // Given default values for children members, produces a new default expression for the requested (parent) member. // </summary> // <param name="node"> Parent member </param> // <returns> Default value for parent member </returns> internal PropagatorResult Visit(EdmMember node) { PropagatorResult result; var nodeType = Helper.GetModelTypeUsage(node); if (Helper.IsScalarType(nodeType.EdmType)) { GetPropagatorResultForPrimitiveType(Helper.AsPrimitive(nodeType.EdmType), out result); } else { // Construct a new 'complex type' (really any structural type) member. var structuralType = (StructuralType)nodeType.EdmType; var members = TypeHelpers.GetAllStructuralMembers(structuralType); var args = new PropagatorResult[members.Count]; for (var ordinal = 0; ordinal < members.Count; ordinal++) // foreach (EdmMember member in members) { args[ordinal] = Visit(members[ordinal]); } result = PropagatorResult.CreateStructuralValue(args, structuralType, false); } return(result); }
// <summary> // Specialization of <see cref="CreatePlaceholder" /> for a relationship set extent. // </summary> private PropagatorResult CreateAssociationSetPlaceholder(AssociationSet associationSet) { DebugCheck.NotNull(associationSet); var endMetadata = associationSet.ElementType.AssociationEndMembers; var endReferenceValues = new PropagatorResult[endMetadata.Count]; // Create a reference expression for each end in the relationship for (var endOrdinal = 0; endOrdinal < endMetadata.Count; endOrdinal++) { var end = endMetadata[endOrdinal]; var entityType = (EntityType)((RefType)end.TypeUsage.EdmType).ElementType; // Retrieve key values for this end var keyValues = new PropagatorResult[entityType.KeyMembers.Count]; for (var memberOrdinal = 0; memberOrdinal < entityType.KeyMembers.Count; memberOrdinal++) { var keyMember = entityType.KeyMembers[memberOrdinal]; var keyValue = CreateMemberPlaceholder(keyMember); keyValues[memberOrdinal] = keyValue; } var endType = entityType.GetKeyRowType(); var refKeys = PropagatorResult.CreateStructuralValue(keyValues, endType, false); endReferenceValues[endOrdinal] = refKeys; } var result = PropagatorResult.CreateStructuralValue(endReferenceValues, associationSet.ElementType, false); return(result); }
// Note that this is called only for association ends. Entities have key values inline. private PropagatorResult CreateEntityKeyResult(IEntityStateEntry stateEntry, EntityKey entityKey) { // get metadata for key var entityType = entityKey.GetEntitySet(m_translator.MetadataWorkspace).ElementType; var keyRowType = entityType.GetKeyRowType(); var keyMetadata = m_translator.GetExtractorMetadata(stateEntry.EntitySet, keyRowType); var keyMemberCount = keyRowType.Properties.Count; var keyValues = new PropagatorResult[keyMemberCount]; for (var ordinal = 0; ordinal < keyRowType.Properties.Count; ordinal++) { EdmMember keyMember = keyRowType.Properties[ordinal]; // retrieve information about this key value var keyMemberInformation = keyMetadata.m_memberMap[ordinal]; var keyIdentifier = m_translator.KeyManager.GetKeyIdentifierForMemberOffset(entityKey, ordinal, keyRowType.Properties.Count); object keyValue = null; if (entityKey.IsTemporary) { // If the EntityKey is temporary, we need to retrieve the appropriate // key value from the entity itself (or in this case, the IEntityStateEntry). var entityEntry = stateEntry.StateManager.GetEntityStateEntry(entityKey); Debug.Assert( entityEntry.State == EntityState.Added, "The corresponding entry for a temp EntityKey should be in the Added State."); keyValue = entityEntry.CurrentValues[keyMember.Name]; } else { // Otherwise, we extract the value from within the EntityKey. keyValue = entityKey.FindValueByName(keyMember.Name); } Debug.Assert(keyValue != null, "keyValue should've been retrieved."); // construct propagator result keyValues[ordinal] = PropagatorResult.CreateKeyValue( keyMemberInformation.Flags, keyValue, stateEntry, keyIdentifier); // see UpdateTranslator.Identifiers for information on key identifiers and ordinals } return(PropagatorResult.CreateStructuralValue(keyValues, keyMetadata.m_type, false)); }
// <summary> // Specialization of <see cref="CreatePlaceholder" /> for an entity set extent. // </summary> private PropagatorResult CreateEntitySetPlaceholder(EntitySet entitySet) { DebugCheck.NotNull(entitySet); var members = entitySet.ElementType.Properties; var memberValues = new PropagatorResult[members.Count]; for (var ordinal = 0; ordinal < members.Count; ordinal++) { var memberValue = CreateMemberPlaceholder(members[ordinal]); memberValues[ordinal] = memberValue; } var result = PropagatorResult.CreateStructuralValue(memberValues, entitySet.ElementType, false); return(result); }
private PropagatorResult CreateEntityKeyResult( IEntityStateEntry stateEntry, EntityKey entityKey) { RowType keyRowType = entityKey.GetEntitySet(this.m_translator.MetadataWorkspace).ElementType.GetKeyRowType(); ExtractorMetadata extractorMetadata = this.m_translator.GetExtractorMetadata(stateEntry.EntitySet, (StructuralType)keyRowType); PropagatorResult[] values = new PropagatorResult[keyRowType.Properties.Count]; for (int memberOffset = 0; memberOffset < keyRowType.Properties.Count; ++memberOffset) { EdmMember property = (EdmMember)keyRowType.Properties[memberOffset]; ExtractorMetadata.MemberInformation member = extractorMetadata.m_memberMap[memberOffset]; int identifierForMemberOffset = this.m_translator.KeyManager.GetKeyIdentifierForMemberOffset(entityKey, memberOffset, keyRowType.Properties.Count); object obj = !entityKey.IsTemporary ? entityKey.FindValueByName(property.Name) : stateEntry.StateManager.GetEntityStateEntry(entityKey).CurrentValues[property.Name]; values[memberOffset] = PropagatorResult.CreateKeyValue(member.Flags, obj, stateEntry, identifierForMemberOffset); } return(PropagatorResult.CreateStructuralValue(values, extractorMetadata.m_type, false)); }
// <summary> // Converts a record to a propagator result // </summary> // <param name="stateEntry"> state manager entry containing the record </param> // <param name="isModified"> Indicates whether the root element is modified (i.e., whether the type has changed) </param> // <param name="record"> Record to convert </param> // <param name="useCurrentValues"> Indicates whether we are retrieving current or original values. </param> // <param name="translator"> Translator for session context; registers new metadata for the record type if none exists </param> // <param name="modifiedPropertiesBehavior"> Indicates how to determine whether a property is modified. </param> // <returns> Result corresponding to the given record </returns> internal static PropagatorResult ExtractResultFromRecord( IEntityStateEntry stateEntry, bool isModified, IExtendedDataRecord record, bool useCurrentValues, UpdateTranslator translator, ModifiedPropertiesBehavior modifiedPropertiesBehavior) { var structuralType = (StructuralType)record.DataRecordInfo.RecordType.EdmType; var metadata = translator.GetExtractorMetadata(stateEntry.EntitySet, structuralType); var key = stateEntry.EntityKey; var nestedValues = new PropagatorResult[record.FieldCount]; for (var ordinal = 0; ordinal < nestedValues.Length; ordinal++) { nestedValues[ordinal] = metadata.RetrieveMember( stateEntry, record, useCurrentValues, key, ordinal, modifiedPropertiesBehavior); } return(PropagatorResult.CreateStructuralValue(nestedValues, structuralType, isModified)); }
// <summary> // Produce a tuple containing joined rows. // </summary> // <param name="left"> Left row. </param> // <param name="right"> Right row. </param> // <param name="result"> Result change node; used for type information. </param> // <returns> Result of joining the input rows. </returns> private PropagatorResult CreateResultTuple( Tuple <CompositeKey, PropagatorResult> left, Tuple <CompositeKey, PropagatorResult> right, ChangeNode result) { // using ref compare to avoid triggering value based var leftKey = left.Item1; var rightKey = right.Item1; Dictionary <PropagatorResult, PropagatorResult> map = null; if (!ReferenceEquals(null, leftKey) && !ReferenceEquals(null, rightKey) && !ReferenceEquals(leftKey, rightKey)) { // Merge key values from the left and the right (since they're equal, there's a possibility we'll // project values only from the left or the right hand side and lose important context.) var mergedKey = leftKey.Merge(m_parent.m_updateTranslator.KeyManager, rightKey); // create a dictionary so that we can replace key values with merged key values (carrying context // from both sides) map = new Dictionary <PropagatorResult, PropagatorResult>(); for (var i = 0; i < leftKey.KeyComponents.Length; i++) { map[leftKey.KeyComponents[i]] = mergedKey.KeyComponents[i]; map[rightKey.KeyComponents[i]] = mergedKey.KeyComponents[i]; } } var joinRecordValues = new PropagatorResult[2]; joinRecordValues[0] = left.Item2; joinRecordValues[1] = right.Item2; var join = PropagatorResult.CreateStructuralValue(joinRecordValues, (StructuralType)result.ElementType.EdmType, false); // replace with merged key values as appropriate if (null != map) { PropagatorResult replacement; join = join.Replace(original => map.TryGetValue(original, out replacement) ? replacement : original); } return(join); }
public void Returns_rows_affected_when_there_is_a_reader() { var mockPrimitiveType = new Mock <PrimitiveType>(); mockPrimitiveType.Setup(m => m.BuiltInTypeKind).Returns(BuiltInTypeKind.PrimitiveType); mockPrimitiveType.Setup(m => m.PrimitiveTypeKind).Returns(PrimitiveTypeKind.Int32); mockPrimitiveType.Setup(m => m.DataSpace).Returns(DataSpace.CSpace); var memberName = "property"; var edmProperty = new EdmProperty(memberName, TypeUsage.Create(mockPrimitiveType.Object)); var entityType = new EntityType("", "", DataSpace.CSpace, Enumerable.Empty <string>(), new[] { edmProperty }); entityType.SetReadOnly(); var mockUpdateTranslator = new Mock <UpdateTranslator>(MockBehavior.Strict); mockUpdateTranslator.Setup(m => m.CommandTimeout).Returns(() => null); var entityConnection = new Mock <EntityConnection>().Object; mockUpdateTranslator.Setup(m => m.Connection).Returns(entityConnection); var mockDbModificationCommandTree = new Mock <DbModificationCommandTree>(); mockDbModificationCommandTree.SetupGet(m => m.HasReader).Returns(true); var mockDynamicUpdateCommand = new Mock <DynamicUpdateCommand>( new Mock <TableChangeProcessor>().Object, mockUpdateTranslator.Object, ModificationOperator.Delete, PropagatorResult.CreateSimpleValue(PropagatorFlags.NoFlags, value: 0), PropagatorResult.CreateStructuralValue( new[] { PropagatorResult.CreateSimpleValue(PropagatorFlags.NoFlags, value: 0) }, entityType, isModified: false), mockDbModificationCommandTree.Object, /*outputIdentifiers*/ null) { CallBase = true }; var mockDbCommand = new Mock <DbCommand>(); var dbValue = 66; var mockDbDataReader = new Mock <DbDataReader>(); mockDbDataReader.Setup(m => m.GetFieldValueAsync <object>(It.IsAny <int>(), It.IsAny <CancellationToken>())) .Returns(Task.FromResult <object>(dbValue)); var rowsToRead = 2; mockDbDataReader.Setup(m => m.ReadAsync(It.IsAny <CancellationToken>())).Returns( () => { rowsToRead--; return(Task.FromResult(rowsToRead > 0)); }); mockDbDataReader.Setup(m => m.FieldCount).Returns(1); mockDbDataReader.Setup(m => m.GetName(0)).Returns(memberName); mockDbDataReader.Setup(m => m.NextResultAsync(It.IsAny <CancellationToken>())).Returns(Task.FromResult(false)); mockDbCommand.Protected() .Setup <Task <DbDataReader> >("ExecuteDbDataReaderAsync", CommandBehavior.SequentialAccess, It.IsAny <CancellationToken>()) .Returns(Task.FromResult(mockDbDataReader.Object)); var identifierValues = new Dictionary <int, object>(); mockDynamicUpdateCommand.Protected().Setup <DbCommand>("CreateCommand", identifierValues).Returns(mockDbCommand.Object); var generatedValues = new List <KeyValuePair <PropagatorResult, object> >(); var rowsAffectedResult = mockDynamicUpdateCommand.Object.ExecuteAsync(identifierValues, generatedValues, CancellationToken.None).Result; Assert.Equal(1, rowsAffectedResult); Assert.Equal(1, generatedValues.Count); Assert.Equal(dbValue, generatedValues[0].Value); Assert.Equal(0, generatedValues[0].Key.GetSimpleValue()); }
public void Returns_rows_affected_when_there_are_result_columns() { var mockPrimitiveType = new Mock <PrimitiveType>(); mockPrimitiveType.Setup(m => m.BuiltInTypeKind).Returns(BuiltInTypeKind.PrimitiveType); mockPrimitiveType.Setup(m => m.PrimitiveTypeKind).Returns(PrimitiveTypeKind.Int32); mockPrimitiveType.Setup(m => m.DataSpace).Returns(DataSpace.CSpace); var edmProperty = new EdmProperty("property", TypeUsage.Create(mockPrimitiveType.Object)); var entityType = new EntityType("", "", DataSpace.CSpace, Enumerable.Empty <string>(), new[] { edmProperty }); entityType.SetReadOnly(); var stateEntry = new ExtractedStateEntry( EntityState.Unchanged, PropagatorResult.CreateSimpleValue(PropagatorFlags.NoFlags, value: 0), PropagatorResult.CreateStructuralValue( new[] { PropagatorResult.CreateSimpleValue(PropagatorFlags.NoFlags, value: 0) }, entityType, isModified: false), new Mock <IEntityStateEntry>().Object); var updateTranslatorMock = new Mock <UpdateTranslator>(); updateTranslatorMock.Setup(m => m.CommandTimeout).Returns(() => null); var entityConnection = new Mock <EntityConnection>().Object; updateTranslatorMock.Setup(m => m.Connection).Returns(entityConnection); updateTranslatorMock.Setup(m => m.InterceptionContext).Returns(new DbInterceptionContext()); var dbCommandMock = new Mock <DbCommand>(); var stateEntries = new ReadOnlyCollection <IEntityStateEntry>(new List <IEntityStateEntry>()); var mockFunctionUpdateCommand = new Mock <FunctionUpdateCommand>( updateTranslatorMock.Object, stateEntries, stateEntry, dbCommandMock.Object) { CallBase = true }; var dbValue = 66; var dbDataReaderMock = new Mock <DbDataReader>(); dbDataReaderMock.Setup(m => m.GetValue(It.IsAny <int>())).Returns(dbValue); var rowsToRead = 2; dbDataReaderMock.Setup(m => m.Read()).Returns( () => { rowsToRead--; return(rowsToRead > 0); }); dbCommandMock.Protected().Setup <DbDataReader>("ExecuteDbDataReader", CommandBehavior.SequentialAccess).Returns( dbDataReaderMock.Object); var timesSetInputIdentifiers = 0; var identifierValues = new Dictionary <int, object>(); mockFunctionUpdateCommand.Setup(m => m.SetInputIdentifiers(It.IsAny <Dictionary <int, object> >())) .Callback <Dictionary <int, object> >( identifierValuesPassed => { timesSetInputIdentifiers++; Assert.Same(identifierValues, identifierValuesPassed); }); var generatedValues = new List <KeyValuePair <PropagatorResult, object> >(); var mockObjectStateManager = new Mock <ObjectStateManager>(); var objectStateEntryMock = new Mock <ObjectStateEntry>(mockObjectStateManager.Object, null, EntityState.Unchanged); var currentValueRecordMock = new Mock <CurrentValueRecord>(objectStateEntryMock.Object); var idColumn = new KeyValuePair <string, PropagatorResult>( "ID", PropagatorResult.CreateServerGenSimpleValue( PropagatorFlags.NoFlags, /*value:*/ 0, currentValueRecordMock.Object, recordOrdinal: 0)); mockFunctionUpdateCommand.Protected().Setup <List <KeyValuePair <string, PropagatorResult> > >("ResultColumns") .Returns((new[] { idColumn }).ToList()); var rowsAffectedResult = mockFunctionUpdateCommand.Object.Execute(identifierValues, generatedValues); Assert.Equal(1, rowsAffectedResult); Assert.Equal(1, timesSetInputIdentifiers); Assert.Equal(1, generatedValues.Count); Assert.Same(idColumn.Value, generatedValues[0].Key); Assert.Equal(dbValue, generatedValues[0].Value); }