Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / Map / Update / Internal / DynamicUpdateCommand.cs / 1305376 / DynamicUpdateCommand.cs
//---------------------------------------------------------------------- //// Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- using System.Collections.Generic; using System.Data.Common.CommandTrees; using System.Data.Metadata.Edm; using System.Data.Common; using System.Data.EntityClient; using System.Diagnostics; using System.Data.Common.Utils; using System.Linq; using System.Data.Common.CommandTrees.ExpressionBuilder; namespace System.Data.Mapping.Update.Internal { internal sealed class DynamicUpdateCommand : UpdateCommand { private readonly ModificationOperator m_operator; private readonly TableChangeProcessor m_processor; private readonly List> m_inputIdentifiers; private readonly Dictionary m_outputIdentifiers; private readonly DbModificationCommandTree m_modificationCommandTree; internal DynamicUpdateCommand(TableChangeProcessor processor, UpdateTranslator translator, ModificationOperator op, PropagatorResult originalValues, PropagatorResult currentValues, DbModificationCommandTree tree, Dictionary outputIdentifiers) : base(originalValues, currentValues) { m_processor = EntityUtil.CheckArgumentNull(processor, "processor"); m_operator = op; m_modificationCommandTree = EntityUtil.CheckArgumentNull(tree, "commandTree"); m_outputIdentifiers = outputIdentifiers; // may be null (not all commands have output identifiers) // initialize identifier information (supports lateral propagation of server gen values) if (ModificationOperator.Insert == op || ModificationOperator.Update == op) { const int capacity = 2; // "average" number of identifiers per row m_inputIdentifiers = new List >(capacity); foreach (KeyValuePair member in Helper.PairEnumerations(TypeHelpers.GetAllStructuralMembers(this.CurrentValues.StructuralType), this.CurrentValues.GetMemberValues())) { DbSetClause setter; int identifier = member.Value.Identifier; if (PropagatorResult.NullIdentifier != identifier && TryGetSetterExpression(tree, member.Key, op, out setter)) // can find corresponding setter { foreach (int principal in translator.KeyManager.GetPrincipals(identifier)) { m_inputIdentifiers.Add(new KeyValuePair (principal, setter)); } } } } } // effects: try to find setter expression for the given member // requires: command tree must be an insert or update tree (since other DML trees hnabve private static bool TryGetSetterExpression(DbModificationCommandTree tree, EdmMember member, ModificationOperator op, out DbSetClause setter) { Debug.Assert(op == ModificationOperator.Insert || op == ModificationOperator.Update, "only inserts and updates have setters"); IEnumerable clauses; if (ModificationOperator.Insert == op) { clauses = ((DbInsertCommandTree)tree).SetClauses; } else { clauses = ((DbUpdateCommandTree)tree).SetClauses; } foreach (DbSetClause setClause in clauses) { // check if this is the correct setter if (((DbPropertyExpression)setClause.Property).Property.EdmEquals(member)) { setter = setClause; return true; } } // no match found setter = null; return false; } internal override long Execute(UpdateTranslator translator, EntityConnection connection, Dictionary identifierValues, List > generatedValues) { // Compile command DbCommand command = this.CreateCommand(translator, identifierValues); // configure command to use the connection and transaction for this session command.Transaction = ((null != connection.CurrentTransaction) ? connection.CurrentTransaction.StoreTransaction : null); command.Connection = connection.StoreConnection; if (translator.CommandTimeout.HasValue) { command.CommandTimeout = translator.CommandTimeout.Value; } // Execute the query int rowsAffected; if (m_modificationCommandTree.HasReader) { // retrieve server gen results rowsAffected = 0; using (DbDataReader reader = command.ExecuteReader(CommandBehavior.SequentialAccess)) { if (reader.Read()) { rowsAffected++; IBaseList members = TypeHelpers.GetAllStructuralMembers(this.CurrentValues.StructuralType); for (int ordinal = 0; ordinal < reader.FieldCount; ordinal++) { // column name of result corresponds to column name of table string columnName = reader.GetName(ordinal); object value = reader.GetValue(ordinal); // retrieve result which includes the context for back-propagation int columnOrdinal = members.IndexOf(members[columnName]); PropagatorResult result = this.CurrentValues.GetMemberValue(columnOrdinal); // register for back-propagation generatedValues.Add(new KeyValuePair (result, value)); // register identifier if it exists int identifier = result.Identifier; if (PropagatorResult.NullIdentifier != identifier) { identifierValues.Add(identifier, value); } } } // Consume the current reader (and subsequent result sets) so that any errors // executing the command can be intercepted CommandHelper.ConsumeReader(reader); } } else { rowsAffected = command.ExecuteNonQuery(); } return rowsAffected; } /// /// Gets DB command definition encapsulating store logic for this command. /// private DbCommand CreateCommand(UpdateTranslator translator, DictionaryidentifierValues) { DbModificationCommandTree commandTree = m_modificationCommandTree; // check if any server gen identifiers need to be set if (null != m_inputIdentifiers) { Dictionary modifiedClauses = new Dictionary (); for (int idx = 0; idx < m_inputIdentifiers.Count; idx++) { KeyValuePair inputIdentifier = m_inputIdentifiers[idx]; object value; if (identifierValues.TryGetValue(inputIdentifier.Key, out value)) { // reset the value of the identifier DbSetClause newClause = new DbSetClause(inputIdentifier.Value.Property, DbExpressionBuilder.Constant(value)); modifiedClauses[inputIdentifier.Value] = newClause; m_inputIdentifiers[idx] = new KeyValuePair (inputIdentifier.Key, newClause); } } commandTree = RebuildCommandTree(commandTree, modifiedClauses); } return translator.CreateCommand(commandTree); } private DbModificationCommandTree RebuildCommandTree(DbModificationCommandTree originalTree, Dictionary clauseMappings) { if (clauseMappings.Count == 0) { return originalTree; } DbModificationCommandTree result; Debug.Assert(originalTree.CommandTreeKind == DbCommandTreeKind.Insert || originalTree.CommandTreeKind == DbCommandTreeKind.Update, "Set clauses specified for a modification tree that is not an update or insert tree?"); if (originalTree.CommandTreeKind == DbCommandTreeKind.Insert) { DbInsertCommandTree insertTree = (DbInsertCommandTree)originalTree; result = new DbInsertCommandTree(insertTree.MetadataWorkspace, insertTree.DataSpace, insertTree.Target, ReplaceClauses(insertTree.SetClauses, clauseMappings).AsReadOnly(), insertTree.Returning); } else { DbUpdateCommandTree updateTree = (DbUpdateCommandTree)originalTree; result = new DbUpdateCommandTree(updateTree.MetadataWorkspace, updateTree.DataSpace, updateTree.Target, updateTree.Predicate, ReplaceClauses(updateTree.SetClauses, clauseMappings).AsReadOnly(), updateTree.Returning); } return result; } /// /// Creates a new list of modification clauses with the specified remapped clauses replaced. /// private ListReplaceClauses(IList originalClauses, Dictionary mappings) { List result = new List (originalClauses.Count); for (int idx = 0; idx < originalClauses.Count; idx++) { DbSetClause replacementClause; if (mappings.TryGetValue((DbSetClause)originalClauses[idx], out replacementClause)) { result.Add(replacementClause); } else { result.Add(originalClauses[idx]); } } return result; } internal ModificationOperator Operator { get { return m_operator; } } internal override EntitySet Table { get { return this.m_processor.Table; } } internal override IEnumerable InputIdentifiers { get { if (null == m_inputIdentifiers) { yield break; } else { foreach (KeyValuePair inputIdentifier in m_inputIdentifiers) { yield return inputIdentifier.Key; } } } } internal override IEnumerable OutputIdentifiers { get { if (null == m_outputIdentifiers) { return Enumerable.Empty (); } return m_outputIdentifiers.Keys; } } internal override UpdateCommandKind Kind { get { return UpdateCommandKind.Dynamic; } } internal override IList GetStateEntries(UpdateTranslator translator) { List stateEntries = new List (2); if (null != this.OriginalValues) { foreach (IEntityStateEntry stateEntry in SourceInterpreter.GetAllStateEntries( this.OriginalValues, translator, this.Table)) { stateEntries.Add(stateEntry); } } if (null != this.CurrentValues) { foreach (IEntityStateEntry stateEntry in SourceInterpreter.GetAllStateEntries( this.CurrentValues, translator, this.Table)) { stateEntries.Add(stateEntry); } } return stateEntries; } internal override int CompareToType(UpdateCommand otherCommand) { Debug.Assert(!object.ReferenceEquals(this, otherCommand), "caller is supposed to ensure otherCommand is different reference"); DynamicUpdateCommand other = (DynamicUpdateCommand)otherCommand; // order by operation type int result = (int)this.Operator - (int)other.Operator; if (0 != result) { return result; } // order by Container.Table result = StringComparer.Ordinal.Compare(this.m_processor.Table.Name, other.m_processor.Table.Name); if (0 != result) { return result; } result = StringComparer.Ordinal.Compare(this.m_processor.Table.EntityContainer.Name, other.m_processor.Table.EntityContainer.Name); if (0 != result) { return result; } // order by table key PropagatorResult thisResult = (this.Operator == ModificationOperator.Delete ? this.OriginalValues : this.CurrentValues); PropagatorResult otherResult = (other.Operator == ModificationOperator.Delete ? other.OriginalValues : other.CurrentValues); for (int i = 0; i < m_processor.KeyOrdinals.Length; i++) { int keyOrdinal = m_processor.KeyOrdinals[i]; object thisValue = thisResult.GetMemberValue(keyOrdinal).GetSimpleValue(); object otherValue = otherResult.GetMemberValue(keyOrdinal).GetSimpleValue(); result = ByValueComparer.Default.Compare(thisValue, otherValue); if (0 != result) { return result; } } // If the result is still zero, it means key values are all the same. Switch to synthetic identifiers // to differentiate. for (int i = 0; i < m_processor.KeyOrdinals.Length; i++) { int keyOrdinal = m_processor.KeyOrdinals[i]; int thisValue = thisResult.GetMemberValue(keyOrdinal).Identifier; int otherValue = otherResult.GetMemberValue(keyOrdinal).Identifier; result = thisValue - otherValue; if (0 != result) { return result; } } return result; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Popup.cs
- Vector3DCollectionConverter.cs
- ConsoleTraceListener.cs
- SqlBooleanMismatchVisitor.cs
- UIElement.cs
- TypeConverterMarkupExtension.cs
- TextDecorationCollectionConverter.cs
- __Filters.cs
- SoapExtensionReflector.cs
- ResourceContainerWrapper.cs
- WebEventCodes.cs
- TagPrefixCollection.cs
- ScrollBar.cs
- XmlEncoding.cs
- SubMenuStyle.cs
- SqlDataSourceConfigureSelectPanel.cs
- DrawListViewColumnHeaderEventArgs.cs
- XmlRawWriter.cs
- ListView.cs
- ValidationRuleCollection.cs
- ProfilePropertySettings.cs
- CombinedGeometry.cs
- WindowsEditBox.cs
- Vector3DAnimationBase.cs
- TileBrush.cs
- Matrix3DStack.cs
- Pkcs9Attribute.cs
- ValidatorUtils.cs
- Animatable.cs
- MimeXmlImporter.cs
- CommandField.cs
- CodeSubDirectory.cs
- sqlstateclientmanager.cs
- XmlDictionary.cs
- MenuItem.cs
- Italic.cs
- CustomValidator.cs
- ShutDownListener.cs
- SocketSettings.cs
- ElementNotEnabledException.cs
- ControlParameter.cs
- IPipelineRuntime.cs
- MoveSizeWinEventHandler.cs
- HeaderedItemsControl.cs
- TextCompositionEventArgs.cs
- DLinqAssociationProvider.cs
- Polygon.cs
- HtmlControl.cs
- IChannel.cs
- UnknownBitmapDecoder.cs
- HttpRawResponse.cs
- SetStoryboardSpeedRatio.cs
- WindowsTokenRoleProvider.cs
- thaishape.cs
- TextSelectionProcessor.cs
- RequestContextBase.cs
- Screen.cs
- PointAnimationUsingKeyFrames.cs
- JsonReaderDelegator.cs
- CreateRefExpr.cs
- SafeUserTokenHandle.cs
- DataViewManagerListItemTypeDescriptor.cs
- SecurityKeyUsage.cs
- JsonGlobals.cs
- ListCommandEventArgs.cs
- PolyBezierSegment.cs
- TableSectionStyle.cs
- EnumBuilder.cs
- SecurityContext.cs
- FormatVersion.cs
- DBCommand.cs
- DropShadowBitmapEffect.cs
- RoleGroupCollection.cs
- SQLInt16Storage.cs
- ResizeGrip.cs
- CorrelationService.cs
- CacheVirtualItemsEvent.cs
- ExpandSegment.cs
- WebHttpSecurityModeHelper.cs
- XmlDigitalSignatureProcessor.cs
- SimpleHandlerBuildProvider.cs
- CacheSection.cs
- RegionIterator.cs
- Int64Animation.cs
- FrameworkContentElement.cs
- ProfileManager.cs
- BasicCellRelation.cs
- TableHeaderCell.cs
- TextOptions.cs
- SiteMapPath.cs
- WebPartEventArgs.cs
- Visual.cs
- SocketElement.cs
- Panel.cs
- RequiredArgumentAttribute.cs
- CompoundFileReference.cs
- DbDataReader.cs
- HighlightVisual.cs
- WebAdminConfigurationHelper.cs
- HierarchicalDataBoundControlAdapter.cs