1 //---------------------------------------------------------------------
2 // <copyright file="IEntityWrapper.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner       avickers
7 // @backupOwner jeffders
8 //---------------------------------------------------------------------
9 using System.Collections;
10 using System.Data.Objects.DataClasses;
11 using System.Runtime.CompilerServices;
12 using System.Data.Metadata.Edm;
13 
14 namespace System.Data.Objects.Internal
15 {
16     /// <summary>
17     /// Internally, entities are wrapped in some implementation of this
18     /// interface.  This allows the RelationshipManager and other classes
19     /// to treat POCO entities and traditional entities in the same way
20     /// where ever possible.
21     /// </summary>
22     internal interface IEntityWrapper
23     {
24         /// <summary>
25         /// The Relationship Manager that is associated with the wrapped entity.
26         /// </summary>
27         RelationshipManager RelationshipManager { get; }
28 
29         /// <summary>
30         /// Information about whether or not the entity instance actually owns and uses its RelationshipManager
31         /// This is used to determine how to do relationship fixup in some cases
32         /// </summary>
33         bool OwnsRelationshipManager { get; }
34 
35         /// <summary>
36         /// The actual entity that is wrapped by this wrapper object.
37         /// </summary>
38         object Entity { get; }
39 
40         /// <summary>
41         /// If this IEntityWrapper is tracked, accesses the ObjectStateEntry that is used in the state manager
42         /// </summary>
43         EntityEntry ObjectStateEntry { get; set; }
44 
45         /// <summary>
46         /// Ensures that the collection with the given name is not null by setting a new empty
47         /// collection onto the property if necessary.
48         /// </summary>
49         /// <param name="collectionName">The name of the collection to operate on</param>
EnsureCollectionNotNull(RelatedEnd relatedEnd)50         void EnsureCollectionNotNull(RelatedEnd relatedEnd);
51 
52         /// <summary>
53         /// The key associated with this entity, which may be null if no key is known.
54         /// </summary>
55         EntityKey EntityKey { get; set; }
56 
57         /// <summary>
58         /// Retrieves the EntityKey from the entity if it implements IEntityWithKey
59         /// </summary>
60         /// <returns>The EntityKey on the entity</returns>
GetEntityKeyFromEntity()61         EntityKey GetEntityKeyFromEntity();
62 
63         /// <summary>
64         /// The context with which the wrapped entity is associated, or null if the entity
65         /// is detached.
66         /// </summary>
67         ObjectContext Context { get; set; }
68 
69         /// <summary>
70         /// The merge option assoicated with the wrapped entity.
71         /// </summary>
72         MergeOption MergeOption { get; }
73 
74         /// <summary>
75         /// Attaches the wrapped entity to the given context.
76         /// </summary>
77         /// <param name="context">the context with which to associate this entity</param>
78         /// <param name="entitySet">the entity set to which the entity belongs</param>
79         /// <param name="mergeOption">the merge option to use</param>
AttachContext(ObjectContext context, EntitySet entitySet, MergeOption mergeOption)80         void AttachContext(ObjectContext context, EntitySet entitySet, MergeOption mergeOption);
81 
82         /// <summary>
83         /// Resets the context with which the wrapped entity is associated.
84         /// </summary>
85         /// <param name="context">the context with which to associate this entity</param>
86         /// <param name="entitySet">the entity set to which the entity belongs</param>
87         /// <param name="mergeOption">the merge option to use</param>
ResetContext(ObjectContext context, EntitySet entitySet, MergeOption mergeOption)88         void ResetContext(ObjectContext context, EntitySet entitySet, MergeOption mergeOption);
89 
90         /// <summary>
91         /// Detaches the wrapped entity from its associated context.
92         /// </summary>
DetachContext()93         void DetachContext();
94 
95         /// <summary>
96         /// Sets the entity's ObjectStateEntry as the entity's change tracker if possible.
97         /// The ObjectStateEntry may be null when a change tracker is being removed from an
98         /// entity.
99         /// </summary>
100         /// <param name="changeTracker">the object to use as a change tracker</param>
SetChangeTracker(IEntityChangeTracker changeTracker)101         void SetChangeTracker(IEntityChangeTracker changeTracker);
102 
103         /// <summary>
104         /// Takes a snapshot of the entity state unless the entity has an associated
105         /// change tracker or the given entry is null, in which case no action is taken.
106         /// </summary>
107         /// <param name="entry">the entity's associated state entry</param>
TakeSnapshot(EntityEntry entry)108         void TakeSnapshot(EntityEntry entry);
109 
110         /// <summary>
111         /// Takes a snapshot of the relationships of the entity stored in the entry
112         /// </summary>
113         /// <param name="entry"></param>
TakeSnapshotOfRelationships(EntityEntry entry)114         void TakeSnapshotOfRelationships(EntityEntry entry);
115 
116         /// <summary>
117         /// The Type object that should be used to identify this entity in o-space.
118         /// This is normally just the type of the entity object, but if the object
119         /// is a proxy that we have generated, then the type of the base class is returned instead.
120         /// This ensures that both proxy entities and normal entities are treated as the
121         /// same kind of entity in the metadata and places where the metadata is used.
122         /// </summary>
123         Type IdentityType { get; }
124 
125         /// <summary>
126         /// Populates a value into a collection of values stored in a property of the entity.
127         /// If the collection to be populated is actually managed by and returned from
128         /// the RelationshipManager when needed, then this method is a no-op.  This is
129         /// typically the case for non-POCO entities.
130         /// </summary>
CollectionAdd(RelatedEnd relatedEnd, object value)131         void CollectionAdd(RelatedEnd relatedEnd, object value);
132 
133         /// <summary>
134         /// Removes a value from a collection of values stored in a property of the entity.
135         /// If the collection to be updated is actually managed by and returned from
136         /// the RelationshipManager when needed, then this method is a no-op.  This is
137         /// typically the case for non-POCO entities.
138         /// </summary>
CollectionRemove(RelatedEnd relatedEnd, object value)139         bool CollectionRemove(RelatedEnd relatedEnd, object value);
140 
141         /// <summary>
142         /// Returns value of the entity's property described by the navigation property.
143         /// </summary>
144         /// <param name="relatedEnd">navigation property to retrieve</param>
145         /// <returns></returns>
GetNavigationPropertyValue(RelatedEnd relatedEnd)146         object GetNavigationPropertyValue(RelatedEnd relatedEnd);
147 
148         /// <summary>
149         /// Populates a single value into a field or property of the entity.
150         /// If the element to be populated is actually managed by and returned from
151         /// the RelationshipManager when needed, then this method is a no-op.  This is
152         /// typically the case for non-POCO entities.
153         /// </summary>
SetNavigationPropertyValue(RelatedEnd relatedEnd, object value)154         void SetNavigationPropertyValue(RelatedEnd relatedEnd, object value);
155 
156         /// <summary>
157         /// Removes a single value from a field or property of the entity.
158         /// If the field or property contains reference to a different object,
159         /// this method is a no-op.
160         /// If the element to be populated is actually managed by and returned from
161         /// the RelationshipManager when needed, then this method is a no-op.  This is
162         /// typically the case for non-POCO entities.
163         /// </summary>
164         /// <param name="value">The value to remove</param>
RemoveNavigationPropertyValue(RelatedEnd relatedEnd, object value)165         void RemoveNavigationPropertyValue(RelatedEnd relatedEnd, object value);
166 
167         /// <summary>
168         /// Sets the given value onto the entity with the registered change either handled by the
169         /// entity itself or by using the given EntityEntry as the change tracker.
170         /// </summary>
171         /// <param name="entry">The state entry of the entity to for which a value should be set</param>
172         /// <param name="member">State member information indicating the member to set</param>
173         /// <param name="ordinal">The ordinal of the member to set</param>
174         /// <param name="target">The object onto which the value should be set; may be the entity, or a contained complex value</param>
175         /// <param name="value">The value to set</param>
SetCurrentValue(EntityEntry entry, StateManagerMemberMetadata member, int ordinal, object target, object value)176         void SetCurrentValue(EntityEntry entry, StateManagerMemberMetadata member, int ordinal, object target, object value);
177 
178         /// <summary>
179         /// Set to true while the process of initalizing RelatedEnd objects for an IPOCO proxy is in process.
180         /// This flag prevents the context from being set onto the related ends, which in turn means that
181         /// the related ends don't need to have keys, which in turn means they don't need to be part of an EntitySet.
182         /// </summary>
183         bool InitializingProxyRelatedEnds { get; set; }
184 
185         /// <summary>
186         /// Updates the current value records using Shaper.UpdateRecord but with additional change tracking logic
187         /// added as required by POCO and proxy entities.  For the simple case of no proxy and an entity with
188         /// a change tracker, this translates into a simple call to ShaperUpdateRecord.
189         /// </summary>
190         /// <param name="value">The value</param>
191         /// <param name="entry">The existing ObjectStateEntry</param>
UpdateCurrentValueRecord(object value, EntityEntry entry)192         void UpdateCurrentValueRecord(object value, EntityEntry entry);
193 
194         /// <summary>
195         /// True if the underlying entity is not capable of tracking changes to relationships such that
196         /// DetectChanges is required to do this.
197         /// </summary>
198         bool RequiresRelationshipChangeTracking { get; }
199     }
200 }
201