1 //---------------------------------------------------------------------
2 // <copyright file="StorageModificationFunctionMapping.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
8 //---------------------------------------------------------------------
12 using System.Collections.Generic;
13 using System.Collections.ObjectModel;
15 using System.Data.Metadata.Edm;
16 using System.Diagnostics;
17 using System.Globalization;
18 using System.Data.Common.Utils;
21 namespace System.Data.Mapping
24 /// Describes modification function mappings for an association set.
26 internal sealed class StorageAssociationSetModificationFunctionMapping
28 internal StorageAssociationSetModificationFunctionMapping(
29 AssociationSet associationSet,
30 StorageModificationFunctionMapping deleteFunctionMapping,
31 StorageModificationFunctionMapping insertFunctionMapping)
33 this.AssociationSet = EntityUtil.CheckArgumentNull(associationSet, "associationSet");
34 this.DeleteFunctionMapping = deleteFunctionMapping;
35 this.InsertFunctionMapping = insertFunctionMapping;
39 /// Association set these functions handles.
41 internal readonly AssociationSet AssociationSet;
44 /// Delete function for this association set.
46 internal readonly StorageModificationFunctionMapping DeleteFunctionMapping;
49 /// Insert function for this association set.
51 internal readonly StorageModificationFunctionMapping InsertFunctionMapping;
53 public override string ToString()
55 return String.Format(CultureInfo.InvariantCulture,
56 "AS{{{0}}}:{3}DFunc={{{1}}},{3}IFunc={{{2}}}", AssociationSet, DeleteFunctionMapping,
57 InsertFunctionMapping, Environment.NewLine + " ");
60 internal void Print(int index)
62 StorageEntityContainerMapping.GetPrettyPrintString(ref index);
63 StringBuilder sb = new StringBuilder();
64 sb.Append("Association Set Function Mapping");
66 sb.Append(this.ToString());
67 Console.WriteLine(sb.ToString());
72 /// Describes modification function mappings for an entity type within an entity set.
74 internal sealed class StorageEntityTypeModificationFunctionMapping
76 internal StorageEntityTypeModificationFunctionMapping(
77 EntityType entityType,
78 StorageModificationFunctionMapping deleteFunctionMapping,
79 StorageModificationFunctionMapping insertFunctionMapping,
80 StorageModificationFunctionMapping updateFunctionMapping)
82 this.EntityType = EntityUtil.CheckArgumentNull(entityType, "entityType");
83 this.DeleteFunctionMapping = deleteFunctionMapping;
84 this.InsertFunctionMapping = insertFunctionMapping;
85 this.UpdateFunctionMapping = updateFunctionMapping;
89 /// Gets (specific) entity type these functions handle.
91 internal readonly EntityType EntityType;
94 /// Gets delete function for the current entity type.
96 internal readonly StorageModificationFunctionMapping DeleteFunctionMapping;
99 /// Gets insert function for the current entity type.
101 internal readonly StorageModificationFunctionMapping InsertFunctionMapping;
104 /// Gets update function for the current entity type.
106 internal readonly StorageModificationFunctionMapping UpdateFunctionMapping;
108 public override string ToString()
110 return String.Format(CultureInfo.InvariantCulture,
111 "ET{{{0}}}:{4}DFunc={{{1}}},{4}IFunc={{{2}}},{4}UFunc={{{3}}}", EntityType, DeleteFunctionMapping,
112 InsertFunctionMapping, UpdateFunctionMapping, Environment.NewLine + " ");
115 internal void Print(int index)
117 StorageEntityContainerMapping.GetPrettyPrintString(ref index);
118 StringBuilder sb = new StringBuilder();
119 sb.Append("Entity Type Function Mapping");
121 sb.Append(this.ToString());
122 Console.WriteLine(sb.ToString());
127 /// Describes modification function binding for change processing of entities or associations.
129 internal sealed class StorageModificationFunctionMapping
131 internal StorageModificationFunctionMapping(
132 EntitySetBase entitySet,
133 EntityTypeBase entityType,
134 EdmFunction function,
135 IEnumerable<StorageModificationFunctionParameterBinding> parameterBindings,
136 FunctionParameter rowsAffectedParameter,
137 IEnumerable<StorageModificationFunctionResultBinding> resultBindings)
139 EntityUtil.CheckArgumentNull(entitySet, "entitySet");
140 this.Function = EntityUtil.CheckArgumentNull(function, "function");
141 this.RowsAffectedParameter = rowsAffectedParameter;
142 this.ParameterBindings = EntityUtil.CheckArgumentNull(parameterBindings, "parameterBindings")
143 .ToList().AsReadOnly();
144 if (null != resultBindings)
146 List<StorageModificationFunctionResultBinding> bindings = resultBindings.ToList();
147 if (0 < bindings.Count)
149 ResultBindings = bindings.AsReadOnly();
152 this.CollocatedAssociationSetEnds = GetReferencedAssociationSetEnds(entitySet as EntitySet, entityType as EntityType, parameterBindings)
158 /// Gets output parameter producing number of rows affected. May be null.
160 internal readonly FunctionParameter RowsAffectedParameter;
163 /// Gets Metadata of function to which we should bind.
165 internal readonly EdmFunction Function;
168 /// Gets bindings for function parameters.
170 internal readonly ReadOnlyCollection<StorageModificationFunctionParameterBinding> ParameterBindings;
173 /// Gets all association set ends collocated in this mapping.
175 internal readonly ReadOnlyCollection<AssociationSetEnd> CollocatedAssociationSetEnds;
178 /// Gets bindings for the results of function evaluation.
180 internal readonly ReadOnlyCollection<StorageModificationFunctionResultBinding> ResultBindings;
182 public override string ToString()
184 return String.Format(CultureInfo.InvariantCulture,
185 "Func{{{0}}}: Prm={{{1}}}, Result={{{2}}}", Function,
186 StringUtil.ToCommaSeparatedStringSorted(ParameterBindings),
187 StringUtil.ToCommaSeparatedStringSorted(ResultBindings));
190 // requires: entitySet must not be null
191 // Yields all referenced association set ends in this mapping.
192 private static IEnumerable<AssociationSetEnd> GetReferencedAssociationSetEnds(EntitySet entitySet, EntityType entityType, IEnumerable<StorageModificationFunctionParameterBinding> parameterBindings)
194 HashSet<AssociationSetEnd> ends = new HashSet<AssociationSetEnd>();
195 if (null != entitySet && null != entityType)
197 foreach (StorageModificationFunctionParameterBinding parameterBinding in parameterBindings)
199 AssociationSetEnd end = parameterBinding.MemberPath.AssociationSetEnd;
206 // If there is a referential constraint, it counts as an implicit mapping of
207 // the association set
208 foreach (AssociationSet assocationSet in MetadataHelper.GetAssociationsForEntitySet(entitySet))
210 ReadOnlyMetadataCollection<ReferentialConstraint> constraints = assocationSet.ElementType.ReferentialConstraints;
211 if (null != constraints)
213 foreach (ReferentialConstraint constraint in constraints)
215 if ((assocationSet.AssociationSetEnds[constraint.ToRole.Name].EntitySet == entitySet) &&
216 (constraint.ToRole.GetEntityType().IsAssignableFrom(entityType)))
218 ends.Add(assocationSet.AssociationSetEnds[constraint.FromRole.Name]);
229 /// Defines a binding from a named result set column to a member taking the value.
231 internal sealed class StorageModificationFunctionResultBinding
233 internal StorageModificationFunctionResultBinding(string columnName, EdmProperty property)
235 this.ColumnName = EntityUtil.CheckArgumentNull(columnName, "columnName");
236 this.Property = EntityUtil.CheckArgumentNull(property, "property");
240 /// Gets the name of the column to bind from the function result set. We use a string
241 /// value rather than EdmMember, since there is no metadata for function result sets.
243 internal readonly string ColumnName;
246 /// Gets the property to be set on the entity.
248 internal readonly EdmProperty Property;
250 public override string ToString()
252 return String.Format(CultureInfo.InvariantCulture,
253 "{0}->{1}", ColumnName, Property);
258 /// Binds a modification function parameter to a member of the entity or association being modified.
260 internal sealed class StorageModificationFunctionParameterBinding
262 internal StorageModificationFunctionParameterBinding(FunctionParameter parameter, StorageModificationFunctionMemberPath memberPath, bool isCurrent)
264 this.Parameter = EntityUtil.CheckArgumentNull(parameter, "parameter");
265 this.MemberPath = EntityUtil.CheckArgumentNull(memberPath, "memberPath");
266 this.IsCurrent = isCurrent;
270 /// Gets the parameter taking the value.
272 internal readonly FunctionParameter Parameter;
275 /// Gets the path to the entity or association member defining the value.
277 internal readonly StorageModificationFunctionMemberPath MemberPath;
280 /// Gets a value indicating whether the current or original
281 /// member value is being bound.
283 internal readonly bool IsCurrent;
285 public override string ToString()
287 return String.Format(CultureInfo.InvariantCulture,
288 "@{0}->{1}{2}", Parameter, IsCurrent ? "+" : "-", MemberPath);
293 /// Describes the location of a member within an entity or association type structure.
295 internal sealed class StorageModificationFunctionMemberPath
297 internal StorageModificationFunctionMemberPath(IEnumerable<EdmMember> members, AssociationSet associationSetNavigation)
299 this.Members = new ReadOnlyCollection<EdmMember>(new List<EdmMember>(
300 EntityUtil.CheckArgumentNull(members, "members")));
301 if (null != associationSetNavigation)
303 Debug.Assert(2 == this.Members.Count, "Association bindings must always consist of the end and the key");
305 // find the association set end
306 this.AssociationSetEnd = associationSetNavigation.AssociationSetEnds[this.Members[1].Name];
311 /// Gets the members in the path from the leaf (the member being bound)
312 /// to the Root of the structure.
314 internal readonly ReadOnlyCollection<EdmMember> Members;
317 /// Gets the association set to which we are navigating via this member. If the value
318 /// is null, this is not a navigation member path.
320 internal readonly AssociationSetEnd AssociationSetEnd;
322 public override string ToString()
324 return String.Format(CultureInfo.InvariantCulture, "{0}{1}",
325 null == AssociationSetEnd ? String.Empty : "[" + AssociationSetEnd.ParentAssociationSet.ToString() + "]",
326 StringUtil.BuildDelimitedList(Members, null, "."));