Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataEntity / System / Data / Map / Update / Internal / DynamicUpdateCommand.cs / 1 / 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;
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)
{
m_processor = EntityUtil.CheckArgumentNull(processor, "processor");
m_operator = op;
OriginalValues = originalValues;
CurrentValues = currentValues;
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(CurrentValues.StructuralType),
CurrentValues.GetMemberValues()))
{
DbSetClause setter;
long identifier = member.Value.Identifier;
if (PropagatorResult.NullIdentifier != identifier &&
TryGetSetterExpression(tree, member.Key, op, out setter)) // can find corresponding setter
{
foreach (long 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 int 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
Int64 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, Dictionary identifierValues)
{
// check if any server gen identifiers need to be set
if (null != m_inputIdentifiers)
{
foreach (KeyValuePair inputIdentifier in m_inputIdentifiers)
{
object value;
if (identifierValues.TryGetValue(inputIdentifier.Key, out value))
{
// reset the value of the identifier
inputIdentifier.Value.Value = m_modificationCommandTree.CreateConstantExpression(value);
}
}
}
return translator.CreateCommand(m_modificationCommandTree);
}
///
/// Gets original values for the row being modified. Set only for delete and
/// update operations.
///
internal readonly PropagatorResult OriginalValues;
///
/// Gets current values for the row being modified. Set only for update and
/// insert operations.
///
internal readonly PropagatorResult CurrentValues;
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 List 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 = Comparer
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- StyleTypedPropertyAttribute.cs
- ExitEventArgs.cs
- TreeNodeBinding.cs
- SqlDependencyListener.cs
- safesecurityhelperavalon.cs
- XmlAttributeOverrides.cs
- ConditionalWeakTable.cs
- ListBoxItemAutomationPeer.cs
- TypeSystem.cs
- ConversionContext.cs
- DesignerUtils.cs
- PersistenceMetadataNamespace.cs
- PersistChildrenAttribute.cs
- sqlcontext.cs
- LinkTarget.cs
- ClientProxyGenerator.cs
- CodeVariableReferenceExpression.cs
- SpeechRecognizer.cs
- TextTreeExtractElementUndoUnit.cs
- ScriptDescriptor.cs
- GuidelineCollection.cs
- RectangleGeometry.cs
- DesignBindingValueUIHandler.cs
- GradientStopCollection.cs
- OverrideMode.cs
- MultiPageTextView.cs
- AttachedPropertyBrowsableAttribute.cs
- BoolLiteral.cs
- GeneratedView.cs
- ContextInformation.cs
- JsonDataContract.cs
- DataSourceXmlSubItemAttribute.cs
- XsdDateTime.cs
- SmiMetaDataProperty.cs
- WindowsFormsSectionHandler.cs
- TableTextElementCollectionInternal.cs
- Brush.cs
- XmlNodeReader.cs
- TabItemAutomationPeer.cs
- ObjectListSelectEventArgs.cs
- _CacheStreams.cs
- DesignerSelectionListAdapter.cs
- CodeSubDirectory.cs
- ServicesUtilities.cs
- HostedNamedPipeTransportManager.cs
- IUnknownConstantAttribute.cs
- TableProviderWrapper.cs
- ThreadStartException.cs
- ParseNumbers.cs
- ServicePointManagerElement.cs
- RemoteWebConfigurationHostStream.cs
- ConfigurationStrings.cs
- MsmqHostedTransportManager.cs
- ScriptingRoleServiceSection.cs
- XmlSchemaComplexContentExtension.cs
- BamlBinaryWriter.cs
- RelationshipEndCollection.cs
- CLRBindingWorker.cs
- ObjectViewQueryResultData.cs
- AdRotator.cs
- SHA512Managed.cs
- FileSystemWatcher.cs
- RetrieveVirtualItemEventArgs.cs
- ProviderCollection.cs
- EntitySqlQueryCacheKey.cs
- AssociationTypeEmitter.cs
- BitmapEffectGroup.cs
- ContentPlaceHolderDesigner.cs
- IdentityNotMappedException.cs
- ScopedKnownTypes.cs
- OleDbTransaction.cs
- ResponseStream.cs
- DataPagerCommandEventArgs.cs
- XPathException.cs
- DbSourceParameterCollection.cs
- XmlnsCache.cs
- CellParaClient.cs
- ModelFactory.cs
- XPathNodeHelper.cs
- FormViewDeleteEventArgs.cs
- HttpsTransportElement.cs
- FontClient.cs
- UTF8Encoding.cs
- StyleSheetRefUrlEditor.cs
- XmlHelper.cs
- SqlDelegatedTransaction.cs
- StyleHelper.cs
- RSAPKCS1SignatureFormatter.cs
- CollectionType.cs
- Environment.cs
- IResourceProvider.cs
- NativeMethods.cs
- BaseCAMarshaler.cs
- ValidationSummary.cs
- DataGridComponentEditor.cs
- ScrollPattern.cs
- DataGridViewCellCollection.cs
- NavigationProgressEventArgs.cs
- MetadataWorkspace.cs
- SafeNativeMethods.cs