Welcome to mirror list, hosted at ThFree Co, Russian Federation.

ObjectStateEntry.cs « Objects « Data « System « System.Data.Entity « referencesource « class « mcs - github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 388559d75c1f6921d932a26fd7080e7762948b61 (plain)
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
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
//---------------------------------------------------------------------
// <copyright file="ObjectStateEntry.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
//
// @owner       [....]
// @backupOwner [....]
//---------------------------------------------------------------------
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Metadata.Edm;
using System.Data.Objects.DataClasses;
using System.Diagnostics;
using System.Collections;

namespace System.Data.Objects
{
    // Detached - nothing

    // Added - _entity & _currentValues only for shadowState

    // Unchanged - _entity & _currentValues only for shadowState
    // Unchanged -> Deleted - _entity & _currentValues only for shadowState

    // Modified - _currentValues & _modifiedFields + _originalValues only on change
    // Modified -> Deleted - _currentValues & _modifiedFields + _originalValues only on change

    /// <summary>
    /// Represets either a entity, entity stub or relationship
    /// </summary>
    public abstract class ObjectStateEntry : IEntityStateEntry, IEntityChangeTracker
    {
        #region common entry fields
        internal ObjectStateManager _cache;
        internal EntitySetBase _entitySet;
        internal EntityState _state;
        #endregion

        #region Constructor
        // ObjectStateEntry will not be detached and creation will be handled from ObjectStateManager
        internal ObjectStateEntry(ObjectStateManager cache, EntitySet entitySet, EntityState state)
        {
            Debug.Assert(cache != null, "cache cannot be null.");

            _cache = cache;
            _entitySet = entitySet;
            _state = state;
        }
        #endregion // Constructor

        #region Public members
        /// <summary>
        /// ObjectStateManager property of ObjectStateEntry.
        /// </summary>
        /// <param></param>
        /// <returns> ObjectStateManager </returns>
        public ObjectStateManager ObjectStateManager
        {
            get
            {
                ValidateState();
                return _cache;
            }
        }

        /// <summary> Extent property of ObjectStateEntry. </summary>
        /// <param></param>
        /// <returns> Extent </returns>
        public EntitySetBase EntitySet
        {
            get
            {
                ValidateState();
                return _entitySet;
            }
        }

        /// <summary>
        /// State property of ObjectStateEntry.
        /// </summary>
        /// <param></param>
        /// <returns> DataRowState </returns>
        public EntityState State
        {
            get
            {
                return _state;
            }
            internal set
            {
                _state = value;
            }
        }

        /// <summary>
        /// Entity property of ObjectStateEntry.
        /// </summary>
        /// <param></param>
        /// <returns> The entity encapsulated by this entry. </returns>
        abstract public object Entity { get; }

        /// <summary>
        /// The EntityKey associated with the ObjectStateEntry
        /// </summary>
        abstract public EntityKey EntityKey { get; internal set; }

        /// <summary>
        /// Determines if this ObjectStateEntry represents a relationship
        /// </summary>
        abstract public bool IsRelationship { get; }

        /// <summary>
        /// Gets bit array indicating which properties are modified.
        /// </summary>
        abstract internal BitArray ModifiedProperties { get; }

        BitArray IEntityStateEntry.ModifiedProperties { get { return this.ModifiedProperties; } }

        /// <summary>
        /// Original values of entity
        /// </summary>
        /// <param></param>
        /// <returns> DbDataRecord </returns>
        [DebuggerBrowsable(DebuggerBrowsableState.Never)] // don't have debugger view expand this
        abstract public DbDataRecord OriginalValues { get; }

        abstract public OriginalValueRecord GetUpdatableOriginalValues();

        /// <summary>
        /// Current values of entity/ DataRow
        /// </summary>
        /// <param></param>
        /// <returns> DbUpdatableDataRecord </returns>
        [DebuggerBrowsable(DebuggerBrowsableState.Never)] // don't have debugger view expand this
        abstract public CurrentValueRecord CurrentValues { get; }

        /// <summary>
        /// API to accept the current values as original values and  mark the entity as Unchanged.
        /// </summary>
        /// <param></param>
        /// <returns></returns>
        abstract public void AcceptChanges();
        
        /// <summary>
        /// API to mark the entity deleted. if entity is in added state, it will be detached
        /// </summary>
        /// <param></param>
        /// <returns> </returns>
        abstract public void Delete();

        /// <summary>
        /// API to return properties that are marked modified
        /// </summary>
        /// <param> </param>
        /// <returns> IEnumerable of modified properties names, names are in term of c-space </returns>
        abstract public IEnumerable<string> GetModifiedProperties();

        /// <summary>
        /// set the state to Modified.
        /// </summary>
        /// <param></param>
        /// <returns></returns>
        /// <exception cref="InvalidOperationException">If State is not Modified or Unchanged</exception>
        ///
        abstract public void SetModified();

        /// <summary>
        /// Marks specified property as modified.
        /// </summary>
        /// <param name="propertyName">This API recognizes the names in terms of OSpace</param>
        /// <exception cref="InvalidOperationException">If State is not Modified or Unchanged</exception>
        ///
        abstract public void SetModifiedProperty(string propertyName);

        /// <summary>
        /// Rejects any changes made to the property with the given name since the property was last loaded,
        /// attached, saved, or changes were accepted. The orginal value of the property is stored and the
        /// property will no longer be marked as modified. 
        /// </summary>
        /// <remarks>
        /// If the result is that no properties of the entity are marked as modified, then the entity will
        /// be marked as Unchanged.
        /// Changes to properties can only rejected for entities that are in the Modified or Unchanged state.
        /// Calling this method for entities in other states (Added, Deleted, or Detached) will result in
        /// an exception being thrown.
        /// Rejecting changes to properties of an Unchanged entity or unchanged properties of a Modifed
        /// is a no-op.
        /// </remarks>
        /// <param name="propertyName">The name of the property to change.</param>
        abstract public void RejectPropertyChanges(string propertyName);

        /// <summary>
        /// Uses DetectChanges to determine whether or not the current value of the property with the given
        /// name is different from its original value. Note that this may be different from the property being
        /// marked as modified since a property which has not changed can still be marked as modified.
        /// </summary>
        /// <remarks>
        /// For complex properties, a new instance of the complex object which has all the same property
        /// values as the original instance is not considered to be different by this method.
        /// </remarks>
        /// <param name="propertyName">The name of the property.</param>
        /// <returns>True if the property has changed; false otherwise.</returns>
        abstract public bool IsPropertyChanged(string propertyName);

        /// <summary>
        /// Returns the RelationshipManager for the entity represented by this ObjectStateEntry.
        /// Note that a RelationshipManager objects can only be returned if this entry represents a
        /// full entity.  Key-only entries (stubs) and entries representing relationships do not
        /// have associated RelationshipManagers.
        /// </summary>
        /// <exception cref="InvalidOperationException">The entry is a stub or represents a relationship</exception>
        abstract public RelationshipManager RelationshipManager
        {
            get;
        }

        /// <summary>
        /// Changes state of the entry to the specified <paramref name="state"/>
        /// </summary>
        /// <param name="state">The requested state</param>
        abstract public void ChangeState(EntityState state);

        /// <summary>
        /// Apply modified properties to the original object.
        /// </summary>
        /// <param name="current">object with modified properties</param>
        abstract public void ApplyCurrentValues(object currentEntity);

        /// <summary>
        /// Apply original values to the entity.
        /// </summary>
        /// <param name="original">The object with original values</param>
        abstract public void ApplyOriginalValues(object originalEntity);

        #endregion // Public members

        #region IEntityStateEntry
        IEntityStateManager IEntityStateEntry.StateManager
        {
            get
            {
                return (IEntityStateManager)this.ObjectStateManager;
            }
        }

        // must explicitly implement this because interface is internal & so is the property on the
        // class itself -- apparently the compiler won't let anything marked as internal be part of
        // an interface (even if the interface is also internal)
        bool IEntityStateEntry.IsKeyEntry
        {
            get
            {
                return this.IsKeyEntry;
            }
        }
        #endregion // IEntityStateEntry

        #region Public IEntityChangeTracker

        /// <summary>
        /// Used to report that a scalar entity property is about to change
        /// The current value of the specified property is cached when this method is called.
        /// </summary>
        /// <param name="entityMemberName">The name of the entity property that is changing</param>
        void IEntityChangeTracker.EntityMemberChanging(string entityMemberName)
        {
            this.EntityMemberChanging(entityMemberName);
        }

        /// <summary>
        /// Used to report that a scalar entity property has been changed
        /// The property value that was cached during EntityMemberChanging is now
        /// added to OriginalValues
        /// </summary>
        /// <param name="entityMemberName">The name of the entity property that has changing</param>
        void IEntityChangeTracker.EntityMemberChanged(string entityMemberName)
        {
            this.EntityMemberChanged(entityMemberName);
        }

        /// <summary>
        /// Used to report that a complex property is about to change
        /// The current value of the specified property is cached when this method is called.
        /// </summary>
        /// <param name="entityMemberName">The name of the top-level entity property that is changing</param>
        /// <param name="complexObject">The complex object that contains the property that is changing</param>
        /// <param name="complexObjectMemberName">The name of the property that is changing on complexObject</param>
        void IEntityChangeTracker.EntityComplexMemberChanging(string entityMemberName, object complexObject, string complexObjectMemberName)
        {
            this.EntityComplexMemberChanging(entityMemberName, complexObject, complexObjectMemberName);
        }

        /// <summary>
        /// Used to report that a complex property has been changed
        /// The property value that was cached during EntityMemberChanging is now added to OriginalValues
        /// </summary>
        /// <param name="entityMemberName">The name of the top-level entity property that has changed</param>
        /// <param name="complexObject">The complex object that contains the property that changed</param>
        /// <param name="complexObjectMemberName">The name of the property that changed on complexObject</param>
        void IEntityChangeTracker.EntityComplexMemberChanged(string entityMemberName, object complexObject, string complexObjectMemberName)
        {
            this.EntityComplexMemberChanged(entityMemberName, complexObject, complexObjectMemberName);
        }

        /// <summary>
        /// Returns the EntityState from the ObjectStateEntry
        /// </summary>
        EntityState IEntityChangeTracker.EntityState
        {
            get
            {
                return this.State;
            }
        }

        #endregion // IEntityChangeTracker

        #region Internal members

        abstract internal bool IsKeyEntry { get; }

        abstract internal int GetFieldCount(StateManagerTypeMetadata metadata);

        abstract internal Type GetFieldType(int ordinal, StateManagerTypeMetadata metadata);

        abstract internal string GetCLayerName(int ordinal, StateManagerTypeMetadata metadata);

        abstract internal int GetOrdinalforCLayerName(string name, StateManagerTypeMetadata metadata);

        abstract internal void RevertDelete();

        abstract internal void SetModifiedAll();

        abstract internal void EntityMemberChanging(string entityMemberName);
        abstract internal void EntityMemberChanged(string entityMemberName);
        abstract internal void EntityComplexMemberChanging(string entityMemberName, object complexObject, string complexObjectMemberName);
        abstract internal void EntityComplexMemberChanged(string entityMemberName, object complexObject, string complexObjectMemberName);

        /// <summary>
        /// Reuse or create a new (Entity)DataRecordInfo.
        /// </summary>
        abstract internal DataRecordInfo GetDataRecordInfo(StateManagerTypeMetadata metadata, object userObject);

        virtual internal void Reset()
        {
            _cache = null;
            _entitySet = null;
            _state = EntityState.Detached;
        }

        internal void ValidateState()
        {
            if (_state == EntityState.Detached)
            {
                throw EntityUtil.ObjectStateEntryinInvalidState();
            }
            Debug.Assert(null != _cache, "null ObjectStateManager");
            Debug.Assert(null != _entitySet, "null EntitySetBase");
        }

        #endregion // Internal members
    }

    internal struct StateManagerValue
    {
        internal StateManagerMemberMetadata memberMetadata;
        internal object userObject;
        internal object originalValue;

        internal StateManagerValue(StateManagerMemberMetadata metadata, object instance, object value)
        {
            memberMetadata = metadata;
            userObject = instance;
            originalValue = value;
        }
    }

    internal enum ObjectStateValueRecord
    {
        OriginalReadonly = 0,
        CurrentUpdatable = 1,
        OriginalUpdatableInternal = 2,
        OriginalUpdatablePublic = 3,
    }


    // This class is used in Referential Integrity Constraints feature.
    // It is used to get around the problem of enumerating dictionary contents, 
    // but allowing update of the value without breaking the enumerator.
    internal sealed class IntBox
    {
        private int val;

        internal IntBox(int val)
        {
            this.val = val;
        }

        internal int Value 
        {
            get
            {
                return val;
            }

            set 
            {
                val = value;
            }
        }
    }
}