1 //---------------------------------------------------------------------
2 // <copyright file="Propagator.JoinPropagator.SubstitutingCloneVisitor.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
10 using System.Collections.Generic;
11 using System.Data.Common;
13 namespace System.Data.Mapping.Update.Internal
15 internal partial class Propagator
17 private partial class JoinPropagator
20 /// Describes the mode of behavior for the <see cref="PlaceholderPopulator"/>.
22 private enum PopulateMode
25 /// Produce a null extension record (for outer joins) marked as modified
29 /// Produce a null extension record (for outer joins) marked as preserve
33 /// Produce a placeholder for a record that is known to exist but whose specific
34 /// values are unknown.
40 /// Fills in a placeholder with join key data (also performs a clone so that the
41 /// placeholder can be reused).
44 /// Clones of placeholder nodes are created when either the structure of the node
45 /// needs to change or the record markup for the node needs to change.
47 private static class PlaceholderPopulator
51 /// Construct a new placeholder with the shape of the given placeholder. Key values are
52 /// injected into the resulting place holder and default values are substituted with
53 /// either propagator constants or progagator nulls depending on the mode established
54 /// by the <paramref name="mode"/> flag.
57 /// The key is essentially an array of values. The key map indicates that for a particular
58 /// placeholder an expression (keyMap.Keys) corresponds to some ordinal in the key array.
60 /// <param name="placeholder">Placeholder to clone</param>
61 /// <param name="key">Key to substitute</param>
62 /// <param name="placeholderKey">Key elements in the placeholder (ordinally aligned with 'key')</param>
63 /// <param name="mode">Mode of operation.</param>
64 /// <param name="translator">Translator context.</param>
65 /// <returns>Cloned placeholder with key values</returns>
66 internal static PropagatorResult Populate(PropagatorResult placeholder, CompositeKey key,
67 CompositeKey placeholderKey, PopulateMode mode, UpdateTranslator translator)
69 EntityUtil.CheckArgumentNull(placeholder, "placeholder");
70 EntityUtil.CheckArgumentNull(key, "key");
71 EntityUtil.CheckArgumentNull(placeholderKey, "placeholderKey");
72 EntityUtil.CheckArgumentNull(translator, "translator");
74 // Figure out which flags to apply to generated elements.
75 bool isNull = mode == PopulateMode.NullModified || mode == PopulateMode.NullPreserve;
76 bool preserve = mode == PopulateMode.NullPreserve || mode == PopulateMode.Unknown;
77 PropagatorFlags flags = PropagatorFlags.NoFlags;
78 if (!isNull) { flags |= PropagatorFlags.Unknown; } // only null values are known
79 if (preserve) { flags |= PropagatorFlags.Preserve; }
81 PropagatorResult result = placeholder.Replace(node =>
83 // See if this is a key element
85 for (int i = 0; i < placeholderKey.KeyComponents.Length; i++)
87 if (placeholderKey.KeyComponents[i] == node)
97 return key.KeyComponents[keyIndex];
101 // for simple entries, just return using the markup context for this
103 object value = isNull ? null : node.GetSimpleValue();
104 return PropagatorResult.CreateSimpleValue(flags, value);