Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Mapping / StorageModificationFunctionMapping.cs
1 //---------------------------------------------------------------------
2 // <copyright file="StorageModificationFunctionMapping.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner       [....]
7 // @backupOwner [....]
8 //---------------------------------------------------------------------
9
10
11 using System;
12 using System.Collections.Generic;
13 using System.Collections.ObjectModel;
14 using System.Text;
15 using System.Data.Metadata.Edm;
16 using System.Diagnostics;
17 using System.Globalization;
18 using System.Data.Common.Utils;
19 using System.Linq;
20
21 namespace System.Data.Mapping
22 {
23     /// <summary>
24     /// Describes modification function mappings for an association set.
25     /// </summary>
26     internal sealed class StorageAssociationSetModificationFunctionMapping
27     {
28         internal StorageAssociationSetModificationFunctionMapping(
29             AssociationSet associationSet,
30             StorageModificationFunctionMapping deleteFunctionMapping,
31             StorageModificationFunctionMapping insertFunctionMapping)
32         {
33             this.AssociationSet = EntityUtil.CheckArgumentNull(associationSet, "associationSet");
34             this.DeleteFunctionMapping = deleteFunctionMapping;
35             this.InsertFunctionMapping = insertFunctionMapping;
36         }
37
38         /// <summary>
39         /// Association set these functions handles.
40         /// </summary>
41         internal readonly AssociationSet AssociationSet;
42
43         /// <summary>
44         /// Delete function for this association set.
45         /// </summary>
46         internal readonly StorageModificationFunctionMapping DeleteFunctionMapping;
47
48         /// <summary>
49         /// Insert function for this association set.
50         /// </summary>
51         internal readonly StorageModificationFunctionMapping InsertFunctionMapping;
52
53         public override string ToString()
54         {
55             return String.Format(CultureInfo.InvariantCulture,
56                 "AS{{{0}}}:{3}DFunc={{{1}}},{3}IFunc={{{2}}}", AssociationSet, DeleteFunctionMapping,
57                 InsertFunctionMapping, Environment.NewLine + "  ");
58         }
59
60         internal void Print(int index)
61         {
62             StorageEntityContainerMapping.GetPrettyPrintString(ref index);
63             StringBuilder sb = new StringBuilder();
64             sb.Append("Association Set Function Mapping");
65             sb.Append("   ");
66             sb.Append(this.ToString());
67             Console.WriteLine(sb.ToString());
68         }
69     }
70
71     /// <summary>
72     /// Describes modification function mappings for an entity type within an entity set.
73     /// </summary>
74     internal sealed class StorageEntityTypeModificationFunctionMapping
75     {
76         internal StorageEntityTypeModificationFunctionMapping(
77             EntityType entityType,
78             StorageModificationFunctionMapping deleteFunctionMapping,
79             StorageModificationFunctionMapping insertFunctionMapping,
80             StorageModificationFunctionMapping updateFunctionMapping)
81         {
82             this.EntityType = EntityUtil.CheckArgumentNull(entityType, "entityType");
83             this.DeleteFunctionMapping = deleteFunctionMapping;
84             this.InsertFunctionMapping = insertFunctionMapping;
85             this.UpdateFunctionMapping = updateFunctionMapping;
86         }
87
88         /// <summary>
89         /// Gets (specific) entity type these functions handle.
90         /// </summary>
91         internal readonly EntityType EntityType;
92
93         /// <summary>
94         /// Gets delete function for the current entity type.
95         /// </summary>
96         internal readonly StorageModificationFunctionMapping DeleteFunctionMapping;
97
98         /// <summary>
99         /// Gets insert function for the current entity type.
100         /// </summary>
101         internal readonly StorageModificationFunctionMapping InsertFunctionMapping;
102
103         /// <summary>
104         /// Gets update function for the current entity type.
105         /// </summary>
106         internal readonly StorageModificationFunctionMapping UpdateFunctionMapping;
107
108         public override string ToString()
109         {
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 + "  ");
113         }
114
115         internal void Print(int index)
116         {
117             StorageEntityContainerMapping.GetPrettyPrintString(ref index);
118             StringBuilder sb = new StringBuilder();
119             sb.Append("Entity Type Function Mapping");
120             sb.Append("   ");
121             sb.Append(this.ToString());
122             Console.WriteLine(sb.ToString());
123         }
124     }
125
126     /// <summary>
127     /// Describes modification function binding for change processing of entities or associations.
128     /// </summary>
129     internal sealed class StorageModificationFunctionMapping
130     {
131         internal StorageModificationFunctionMapping(
132             EntitySetBase entitySet,
133             EntityTypeBase entityType,
134             EdmFunction function,
135             IEnumerable<StorageModificationFunctionParameterBinding> parameterBindings,
136             FunctionParameter rowsAffectedParameter,
137             IEnumerable<StorageModificationFunctionResultBinding> resultBindings)
138         {
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)
145             {
146                 List<StorageModificationFunctionResultBinding> bindings = resultBindings.ToList();
147                 if (0 < bindings.Count)
148                 {
149                     ResultBindings = bindings.AsReadOnly();
150                 }
151             }
152             this.CollocatedAssociationSetEnds = GetReferencedAssociationSetEnds(entitySet as EntitySet, entityType as EntityType, parameterBindings)
153                 .ToList()
154                 .AsReadOnly();
155         }
156
157         /// <summary>
158         /// Gets output parameter producing number of rows affected. May be null.
159         /// </summary>
160         internal readonly FunctionParameter RowsAffectedParameter;
161
162         /// <summary>
163         /// Gets Metadata of function to which we should bind.
164         /// </summary>
165         internal readonly EdmFunction Function;
166
167         /// <summary>
168         /// Gets bindings for function parameters.
169         /// </summary>
170         internal readonly ReadOnlyCollection<StorageModificationFunctionParameterBinding> ParameterBindings;
171
172         /// <summary>
173         /// Gets all association set ends collocated in this mapping.
174         /// </summary>
175         internal readonly ReadOnlyCollection<AssociationSetEnd> CollocatedAssociationSetEnds;
176
177         /// <summary>
178         /// Gets bindings for the results of function evaluation.
179         /// </summary>
180         internal readonly ReadOnlyCollection<StorageModificationFunctionResultBinding> ResultBindings;
181
182         public override string ToString()
183         {
184             return String.Format(CultureInfo.InvariantCulture,
185                 "Func{{{0}}}: Prm={{{1}}}, Result={{{2}}}", Function,
186                 StringUtil.ToCommaSeparatedStringSorted(ParameterBindings),
187                 StringUtil.ToCommaSeparatedStringSorted(ResultBindings));
188         }
189
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)
193         {
194             HashSet<AssociationSetEnd> ends = new HashSet<AssociationSetEnd>();
195             if (null != entitySet && null != entityType)
196             {
197                 foreach (StorageModificationFunctionParameterBinding parameterBinding in parameterBindings)
198                 {
199                     AssociationSetEnd end = parameterBinding.MemberPath.AssociationSetEnd;
200                     if (null != end)
201                     {
202                         ends.Add(end);
203                     }
204                 }
205
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))
209                 {
210                     ReadOnlyMetadataCollection<ReferentialConstraint> constraints = assocationSet.ElementType.ReferentialConstraints;
211                     if (null != constraints)
212                     {
213                         foreach (ReferentialConstraint constraint in constraints)
214                         {
215                             if ((assocationSet.AssociationSetEnds[constraint.ToRole.Name].EntitySet == entitySet) &&
216                                   (constraint.ToRole.GetEntityType().IsAssignableFrom(entityType)))
217                             {
218                                 ends.Add(assocationSet.AssociationSetEnds[constraint.FromRole.Name]);
219                             }
220                         }
221                     }
222                 }
223             }
224             return ends;
225         }
226     }
227
228     /// <summary>
229     /// Defines a binding from a named result set column to a member taking the value.
230     /// </summary>
231     internal sealed class StorageModificationFunctionResultBinding
232     {
233         internal StorageModificationFunctionResultBinding(string columnName, EdmProperty property)
234         {
235             this.ColumnName = EntityUtil.CheckArgumentNull(columnName, "columnName");
236             this.Property = EntityUtil.CheckArgumentNull(property, "property");
237         }
238
239         /// <summary>
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.
242         /// </summary>
243         internal readonly string ColumnName;
244
245         /// <summary>
246         /// Gets the property to be set on the entity.
247         /// </summary>
248         internal readonly EdmProperty Property;
249
250         public override string ToString()
251         {
252             return String.Format(CultureInfo.InvariantCulture,
253                 "{0}->{1}", ColumnName, Property);
254         }
255     }
256
257     /// <summary>
258     /// Binds a modification function parameter to a member of the entity or association being modified.
259     /// </summary>
260     internal sealed class StorageModificationFunctionParameterBinding
261     {
262         internal StorageModificationFunctionParameterBinding(FunctionParameter parameter, StorageModificationFunctionMemberPath memberPath, bool isCurrent)
263         {
264             this.Parameter = EntityUtil.CheckArgumentNull(parameter, "parameter");
265             this.MemberPath = EntityUtil.CheckArgumentNull(memberPath, "memberPath");
266             this.IsCurrent = isCurrent;
267         }
268
269         /// <summary>
270         /// Gets the parameter taking the value.
271         /// </summary>
272         internal readonly FunctionParameter Parameter;
273
274         /// <summary>
275         /// Gets the path to the entity or association member defining the value.
276         /// </summary>
277         internal readonly StorageModificationFunctionMemberPath MemberPath;
278
279         /// <summary>
280         /// Gets a value indicating whether the current or original
281         /// member value is being bound.
282         /// </summary>
283         internal readonly bool IsCurrent;
284
285         public override string ToString()
286         {
287             return String.Format(CultureInfo.InvariantCulture,
288                 "@{0}->{1}{2}", Parameter, IsCurrent ? "+" : "-", MemberPath);
289         }
290     }
291
292     /// <summary>
293     /// Describes the location of a member within an entity or association type structure.
294     /// </summary>
295     internal sealed class StorageModificationFunctionMemberPath
296     {
297         internal StorageModificationFunctionMemberPath(IEnumerable<EdmMember> members, AssociationSet associationSetNavigation)
298         {
299             this.Members = new ReadOnlyCollection<EdmMember>(new List<EdmMember>(
300                 EntityUtil.CheckArgumentNull(members, "members")));
301             if (null != associationSetNavigation)
302             {
303                 Debug.Assert(2 == this.Members.Count, "Association bindings must always consist of the end and the key");
304
305                 // find the association set end
306                 this.AssociationSetEnd = associationSetNavigation.AssociationSetEnds[this.Members[1].Name];
307             }
308         }
309
310         /// <summary>
311         /// Gets the members in the path from the leaf (the member being bound)
312         /// to the Root of the structure.
313         /// </summary>
314         internal readonly ReadOnlyCollection<EdmMember> Members;
315
316         /// <summary>
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.
319         /// </summary>
320         internal readonly AssociationSetEnd AssociationSetEnd;
321
322         public override string ToString()
323         {
324             return String.Format(CultureInfo.InvariantCulture, "{0}{1}",
325                 null == AssociationSetEnd ? String.Empty : "[" + AssociationSetEnd.ParentAssociationSet.ToString() + "]",
326                 StringUtil.BuildDelimitedList(Members, null, "."));
327         }
328     }
329 }