File: EntityWrapper.cs

package info (click to toggle)
mono 6.12.0.199%2Bdfsg-6
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 1,296,836 kB
  • sloc: cs: 11,181,803; xml: 2,850,076; ansic: 699,709; cpp: 123,344; perl: 59,361; javascript: 30,841; asm: 21,853; makefile: 20,405; sh: 15,009; python: 4,839; pascal: 925; sql: 859; sed: 16; php: 1
file content (323 lines) | stat: -rw-r--r-- 16,630 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
//---------------------------------------------------------------------
// <copyright file="EntityWrapper.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// @owner       Microsoft
// @backupOwner Microsoft
//---------------------------------------------------------------------
using System.Collections;
using System.Data.Objects.DataClasses;
using System.Diagnostics;
using System.Reflection;
using System.Data.Metadata.Edm;

namespace System.Data.Objects.Internal
{
    /// <summary>
    /// An extension of the EntityWrapper class for entities that are known not to implement
    /// IEntityWithRelationships.  Using this class causes the RelationshipManager to be created
    /// independently.
    /// </summary>
    /// <typeparam name="TEntity">The type of entity wrapped</typeparam>
    internal sealed class EntityWrapperWithoutRelationships<TEntity> : EntityWrapper<TEntity>
    {
        /// <summary>
        /// Constructs a wrapper as part of the materialization process.  This constructor is only used
        /// during materialization where it is known that the entity being wrapped is newly constructed.
        /// This means that some checks are not performed that might be needed when thw wrapper is
        /// created at other times, and information such as the identity type is passed in because
        /// it is readily available in the materializer.
        /// </summary>
        /// <param name="entity">The entity to wrap</param>
        /// <param name="key">The entity's key</param>
        /// <param name="entitySet">The entity set, or null if none is known</param>
        /// <param name="context">The context to which the entity should be attached</param>
        /// <param name="mergeOption">NoTracking for non-tracked entities, AppendOnly otherwise</param>
        /// <param name="identityType">The type of the entity ignoring any possible proxy type</param>
        /// <param name="propertyStrategy">A delegate to create the property accesor strategy object</param>
        /// <param name="changeTrackingStrategy">A delegate to create the change tracking strategy object</param>
        /// <param name="keyStrategy">A delegate to create the entity key strategy object</param>
        internal EntityWrapperWithoutRelationships(TEntity entity, EntityKey key, EntitySet entitySet, ObjectContext context, MergeOption mergeOption, Type identityType,
                                                   Func<object, IPropertyAccessorStrategy> propertyStrategy, Func<object, IChangeTrackingStrategy> changeTrackingStrategy, Func<object, IEntityKeyStrategy> keyStrategy)
            : base(entity, RelationshipManager.Create(), key, entitySet, context, mergeOption, identityType,
                   propertyStrategy, changeTrackingStrategy, keyStrategy)
        {
        }

        /// <summary>
        /// Constructs a wrapper for the given entity.
        /// Note: use EntityWrapperFactory instead of calling this constructor directly.
        /// </summary>
        /// <param name="entity">The entity to wrap</param>
        /// <param name="propertyStrategy">A delegate to create the property accesor strategy object</param>
        /// <param name="changeTrackingStrategy">A delegate to create the change tracking strategy object</param>
        /// <param name="keyStrategy">A delegate to create the entity key strategy object</param>
        internal EntityWrapperWithoutRelationships(TEntity entity, Func<object, IPropertyAccessorStrategy> propertyStrategy, Func<object, IChangeTrackingStrategy> changeTrackingStrategy, Func<object, IEntityKeyStrategy> keyStrategy)
            : base(entity, RelationshipManager.Create(), propertyStrategy, changeTrackingStrategy, keyStrategy)
        {
        }

        public override bool OwnsRelationshipManager
        {
            get { return false; }
        }

        public override void TakeSnapshotOfRelationships(EntityEntry entry)
        {
            entry.TakeSnapshotOfRelationships();
        }

        // See IEntityWrapper documentation
        public override bool RequiresRelationshipChangeTracking
        {
            get { return true; }
        }
    }

    /// <summary>
    /// An extension of the EntityWrapper class for entities that implement IEntityWithRelationships.
    /// Using this class causes creation of the RelationshipManager to be defered to the entity object.
    /// </summary>
    /// <typeparam name="TEntity">The type of entity wrapped</typeparam>
    internal sealed class EntityWrapperWithRelationships<TEntity> : EntityWrapper<TEntity>
        where TEntity : IEntityWithRelationships
    {
        /// <summary>
        /// Constructs a wrapper as part of the materialization process.  This constructor is only used
        /// during materialization where it is known that the entity being wrapped is newly constructed.
        /// This means that some checks are not performed that might be needed when thw wrapper is
        /// created at other times, and information such as the identity type is passed in because
        /// it is readily available in the materializer.
        /// </summary>
        /// <param name="entity">The entity to wrap</param>
        /// <param name="key">The entity's key</param>
        /// <param name="entitySet">The entity set, or null if none is known</param>
        /// <param name="context">The context to which the entity should be attached</param>
        /// <param name="mergeOption">NoTracking for non-tracked entities, AppendOnly otherwise</param>
        /// <param name="identityType">The type of the entity ignoring any possible proxy type</param>
        /// <param name="propertyStrategy">A delegate to create the property accesor strategy object</param>
        /// <param name="changeTrackingStrategy">A delegate to create the change tracking strategy object</param>
        /// <param name="keyStrategy">A delegate to create the entity key strategy object</param>
        internal EntityWrapperWithRelationships(TEntity entity, EntityKey key, EntitySet entitySet, ObjectContext context, MergeOption mergeOption, Type identityType,
                                                Func<object, IPropertyAccessorStrategy> propertyStrategy, Func<object, IChangeTrackingStrategy> changeTrackingStrategy, Func<object, IEntityKeyStrategy> keyStrategy)
            : base(entity, entity.RelationshipManager, key, entitySet, context, mergeOption, identityType,
                   propertyStrategy, changeTrackingStrategy, keyStrategy)
        {
        }

        /// <summary>
        /// Constructs a wrapper for the given entity.
        /// Note: use EntityWrapperFactory instead of calling this constructor directly.
        /// </summary>
        /// <param name="entity">The entity to wrap</param>
        /// <param name="propertyStrategy">A delegate to create the property accesor strategy object</param>
        /// <param name="changeTrackingStrategy">A delegate to create the change tracking strategy object</param>
        /// <param name="keyStrategy">A delegate to create the entity key strategy object</param>
        internal EntityWrapperWithRelationships(TEntity entity, Func<object, IPropertyAccessorStrategy> propertyStrategy, Func<object, IChangeTrackingStrategy> changeTrackingStrategy, Func<object, IEntityKeyStrategy> keyStrategy)
            : base(entity, entity.RelationshipManager, propertyStrategy, changeTrackingStrategy, keyStrategy)
        {
        }

        public override bool OwnsRelationshipManager
        {
            get { return true; }
        }

        public override void TakeSnapshotOfRelationships(EntityEntry entry)
        {
        }

        // See IEntityWrapper documentation
        public override bool RequiresRelationshipChangeTracking
        {
            get { return false; }
        }
    }

    /// <summary>
    /// Implementation of the IEntityWrapper interface that is used for non-null entities that do not implement
    /// all of our standard interfaces: IEntityWithKey, IEntityWithRelationships, and IEntityWithChangeTracker, and
    /// are not proxies.
    /// Different strategies for dealing with these entities are defined by strategy objects that are set into the
    /// wrapper at constructionn time.
    /// </summary>
    internal abstract class EntityWrapper<TEntity> : BaseEntityWrapper<TEntity>
    {
        private readonly TEntity _entity;
        private IPropertyAccessorStrategy _propertyStrategy;
        private IChangeTrackingStrategy _changeTrackingStrategy;
        private IEntityKeyStrategy _keyStrategy;

        /// <summary>
        /// Constructs a wrapper for the given entity.
        /// Note: use EntityWrapperFactory instead of calling this constructor directly.
        /// </summary>
        /// <param name="entity">The entity to wrap</param>
        /// <param name="relationshipManager">The RelationshipManager associated with the entity</param>
        /// <param name="propertyStrategy">A delegate to create the property accesor strategy object</param>
        /// <param name="changeTrackingStrategy">A delegate to create the change tracking strategy object</param>
        /// <param name="keyStrategy">A delegate to create the entity key strategy object</param>
        protected EntityWrapper(TEntity entity, RelationshipManager relationshipManager,
                               Func<object, IPropertyAccessorStrategy> propertyStrategy, Func<object, IChangeTrackingStrategy> changeTrackingStrategy, Func<object, IEntityKeyStrategy> keyStrategy)
            : base(entity, relationshipManager)
        {
            if (relationshipManager == null)
            {
                throw EntityUtil.UnexpectedNullRelationshipManager();
            }
            _entity = entity;
            _propertyStrategy = propertyStrategy(entity);
            _changeTrackingStrategy = changeTrackingStrategy(entity);
            _keyStrategy = keyStrategy(entity);
            Debug.Assert(_changeTrackingStrategy != null, "Change tracking strategy cannot be null.");
            Debug.Assert(_keyStrategy != null, "Key strategy cannot be null.");
        }

        /// <summary>
        /// Constructs a wrapper as part of the materialization process.  This constructor is only used
        /// during materialization where it is known that the entity being wrapped is newly constructed.
        /// This means that some checks are not performed that might be needed when thw wrapper is
        /// created at other times, and information such as the identity type is passed in because
        /// it is readily available in the materializer.
        /// </summary>
        /// <param name="entity">The entity to wrap</param>
        /// <param name="relationshipManager">The RelationshipManager associated with the entity</param>
        /// <param name="key">The entity's key</param>
        /// <param name="entitySet">The entity set, or null if none is known</param>
        /// <param name="context">The context to which the entity should be attached</param>
        /// <param name="mergeOption">NoTracking for non-tracked entities, AppendOnly otherwise</param>
        /// <param name="identityType">The type of the entity ignoring any possible proxy type</param>
        /// <param name="propertyStrategy">A delegate to create the property accesor strategy object</param>
        /// <param name="changeTrackingStrategy">A delegate to create the change tracking strategy object</param>
        /// <param name="keyStrategy">A delegate to create the entity key strategy object</param>
        protected EntityWrapper(TEntity entity, RelationshipManager relationshipManager, EntityKey key, EntitySet set, ObjectContext context, MergeOption mergeOption, Type identityType,
                               Func<object, IPropertyAccessorStrategy> propertyStrategy, Func<object, IChangeTrackingStrategy> changeTrackingStrategy, Func<object, IEntityKeyStrategy> keyStrategy)
            : base(entity, relationshipManager, set, context, mergeOption, identityType)
        {
            if (relationshipManager == null)
            {
                throw EntityUtil.UnexpectedNullRelationshipManager();
            }
            _entity = entity;
            _propertyStrategy = propertyStrategy(entity);
            _changeTrackingStrategy = changeTrackingStrategy(entity);
            _keyStrategy = keyStrategy(entity);
            Debug.Assert(_changeTrackingStrategy != null, "Change tracking strategy cannot be null.");
            Debug.Assert(_keyStrategy != null, "Key strategy cannot be null.");
            _keyStrategy.SetEntityKey(key);
        }

        // See IEntityWrapper documentation
        public override void SetChangeTracker(IEntityChangeTracker changeTracker)
        {
            _changeTrackingStrategy.SetChangeTracker(changeTracker);
        }

        // See IEntityWrapper documentation
        public override void TakeSnapshot(EntityEntry entry)
        {
            _changeTrackingStrategy.TakeSnapshot(entry);
        }

        // See IEntityWrapper documentation
        public override EntityKey EntityKey
        {
            // If no strategy is set, then the key maintained by the wrapper is used,
            // otherwise the request is passed to the strategy.
            get
            {
                return _keyStrategy.GetEntityKey();
            }
            set
            {
                _keyStrategy.SetEntityKey(value);
            }
        }

        public override EntityKey GetEntityKeyFromEntity()
        {
            return _keyStrategy.GetEntityKeyFromEntity();
        }

        public override void CollectionAdd(RelatedEnd relatedEnd, object value)
        {
            if (_propertyStrategy != null)
            {
                _propertyStrategy.CollectionAdd(relatedEnd, value);
            }
        }

        public override bool CollectionRemove(RelatedEnd relatedEnd, object value)
        {
            return _propertyStrategy != null ? _propertyStrategy.CollectionRemove(relatedEnd, value) : false;
        }

        // See IEntityWrapper documentation
        public override void EnsureCollectionNotNull(RelatedEnd relatedEnd)
        {
            if (_propertyStrategy != null)
            {
                object collection = _propertyStrategy.GetNavigationPropertyValue(relatedEnd);
                if (collection == null)
                {
                    collection = _propertyStrategy.CollectionCreate(relatedEnd);
                    _propertyStrategy.SetNavigationPropertyValue(relatedEnd, collection);
                }
            }
        }

        // See IEntityWrapper documentation
        public override object GetNavigationPropertyValue(RelatedEnd relatedEnd)
        {
            return _propertyStrategy != null ? _propertyStrategy.GetNavigationPropertyValue(relatedEnd) : null;
        }

        // See IEntityWrapper documentation
        public override void SetNavigationPropertyValue(RelatedEnd relatedEnd, object value)
        {
            if (_propertyStrategy != null)
            {
                _propertyStrategy.SetNavigationPropertyValue(relatedEnd, value);
            }
        }

        // See IEntityWrapper documentation
        public override void RemoveNavigationPropertyValue(RelatedEnd relatedEnd, object value)
        {
            if (_propertyStrategy != null)
            {
                object currentValue = _propertyStrategy.GetNavigationPropertyValue(relatedEnd);

                if (Object.ReferenceEquals(currentValue, value))
                {
                    _propertyStrategy.SetNavigationPropertyValue(relatedEnd, null);
                }
            }
        }

        // See IEntityWrapper documentation
        public override object Entity
        {
            get { return _entity; }
        }

        // See IEntityWrapper<TEntity> documentation
        public override TEntity TypedEntity
        {
            get { return _entity; }
        }

        // See IEntityWrapper documentation
        public override void SetCurrentValue(EntityEntry entry, StateManagerMemberMetadata member, int ordinal, object target, object value)
        {
            _changeTrackingStrategy.SetCurrentValue(entry, member, ordinal, target, value);
        }

        // See IEntityWrapper documentation
        public override void UpdateCurrentValueRecord(object value, EntityEntry entry)
        {
            _changeTrackingStrategy.UpdateCurrentValueRecord(value, entry);
        }
    }
}