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 Microsoft
// @backupOwner Microsoft
//---------------------------------------------------------------------
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;
}
}
}
}
|