Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / ndp / fx / src / DLinq / Dlinq / Types.cs / 1 / Types.cs
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq.Expressions; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Diagnostics; using System.Runtime.Serialization; using System.Diagnostics.CodeAnalysis; namespace System.Data.Linq { internal static class SourceState{ internal static readonly IEnumerable Loaded = (IEnumerable )new T[] { }; internal static readonly IEnumerable Assigned = (IEnumerable )new T[] { }; } [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification = "[....]: Types are never compared to each other. When comparisons happen it is against the entities that are represented by these constructs.")] public struct Link { T underlyingValue; IEnumerable source; public Link(T value) { this.underlyingValue = value; this.source = null; } public Link(IEnumerable source) { this.source = source; this.underlyingValue = default(T); } public Link(Link link) { this.underlyingValue = link.underlyingValue; this.source = link.source; } public bool HasValue { get { return this.source == null || this.HasLoadedValue || this.HasAssignedValue; } } public bool HasLoadedOrAssignedValue { get { return this.HasLoadedValue || this.HasAssignedValue; } } internal bool HasLoadedValue { get { return this.source == SourceState .Loaded; } } internal bool HasAssignedValue { get { return this.source == SourceState .Assigned; } } internal T UnderlyingValue { get { return this.underlyingValue; } } internal IEnumerable Source { get { return this.source; } } internal bool HasSource { get { return this.source != null && !this.HasAssignedValue && !this.HasLoadedValue; } } public T Value { get { if (this.HasSource) { this.underlyingValue = Enumerable.SingleOrDefault(this.source); this.source = SourceState .Loaded; } return this.underlyingValue; } set { this.underlyingValue = value; this.source = SourceState .Assigned; } } } [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification="[....]: Types are never compared to each other. When comparisons happen it is against the entities that are represented by these constructs.")] public struct EntityRef where TEntity : class { IEnumerable source; TEntity entity; public EntityRef(TEntity entity) { this.entity = entity; this.source = SourceState .Assigned; } public EntityRef(IEnumerable source) { this.source = source; this.entity = default(TEntity); } public EntityRef(EntityRef entityRef) { this.source = entityRef.source; this.entity = entityRef.entity; } public TEntity Entity { get { if (this.HasSource) { IEnumerable src = this.source; this.entity = Enumerable.SingleOrDefault(src); this.source = SourceState .Loaded; } return this.entity; } set { this.entity = value; this.source = SourceState .Assigned; } } public bool HasLoadedOrAssignedValue { get { return this.HasLoadedValue || this.HasAssignedValue; } } internal bool HasValue { get { return this.source == null || this.HasLoadedValue || this.HasAssignedValue; } } internal bool HasLoadedValue { get { return this.source == SourceState .Loaded; } } internal bool HasAssignedValue { get { return this.source == SourceState .Assigned; } } internal bool HasSource { get { return this.source != null && !this.HasLoadedValue && !this.HasAssignedValue; } } internal IEnumerable Source { get { return this.source; } } internal TEntity UnderlyingValue { get { return this.entity; } } } [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Justification="[....]: Naming chosen to represent a different concept from a collection because it is delayed loaded.")] public sealed class EntitySet : IList, IList , IListSource where TEntity : class { IEnumerable source; ItemList entities; ItemList removedEntities; Action onAdd; Action onRemove; TEntity onAddEntity; TEntity onRemoveEntity; int version; private ListChangedEventHandler onListChanged; private bool isModified; private bool isLoaded; bool listChanged; public EntitySet() { } public EntitySet(Action onAdd, Action onRemove) { this.onAdd = onAdd; this.onRemove = onRemove; } internal EntitySet(EntitySet es, bool copyNotifications) { this.source = es.source; foreach (TEntity e in es.entities) entities.Add(e); foreach (TEntity e in es.removedEntities) removedEntities.Add(e); this.version = es.version; if (copyNotifications) { this.onAdd = es.onAdd; this.onRemove = es.onRemove; } } public int Count { get { Load(); return entities.Count; } } public TEntity this[int index] { get { Load(); if (index < 0 || index >= entities.Count) throw Error.ArgumentOutOfRange("index"); return entities[index]; } set { Load(); if (index < 0 || index >= entities.Count) throw Error.ArgumentOutOfRange("index"); if (value == null || IndexOf(value) >= 0) throw Error.ArgumentOutOfRange("value"); CheckModify(); TEntity old = entities[index]; OnRemove(old); OnListChanged(ListChangedType.ItemDeleted, index); OnAdd(value); entities[index] = value; OnModified(); OnListChanged(ListChangedType.ItemAdded, index); } } [SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Justification = "[....]: Naming the parameter entity makes it more discoverable because it is clear what type of data should be added to this collection.")] public void Add(TEntity entity) { if (entity == null) { throw Error.ArgumentNull("entity"); } if (entity != onAddEntity) { CheckModify(); if (!entities.Contains(entity)) { OnAdd(entity); if (this.HasSource) removedEntities.Remove(entity); entities.Add(entity); if (this.IsLoaded) { OnListChanged(ListChangedType.ItemAdded, IndexOf(entity)); } } OnModified(); } } public void AddRange(IEnumerable collection) { if (collection == null) throw Error.ArgumentNull("collection"); CheckModify(); // convert to List in case adding elements here removes them from the 'collection' (ie entityset to entityset assignment) collection = collection.ToList(); foreach (TEntity e in collection) { if (!entities.Contains(e)) { OnAdd(e); if (this.HasSource) removedEntities.Remove(e); entities.Add(e); if (this.IsLoaded){ OnListChanged(ListChangedType.ItemAdded, IndexOf(e)); } } } OnModified(); } public void Assign(IEnumerable entitySource) { Clear(); if (entitySource != null) AddRange(entitySource); // When an entity set is assigned, it is considered loaded. // Since with defer loading enabled, a load is triggered // anyways, this is only necessary in cases where defer loading // is disabled. In such cases, the materializer assigns a // prefetched collection and we want IsLoaded to be true. this.isLoaded = true; } public void Clear() { Load(); CheckModify(); if (entities.Items != null) { List removeList = new List (entities.Items); foreach (TEntity e in removeList) { Remove(e); } } entities = default(ItemList ); OnModified(); OnListChanged(ListChangedType.Reset, 0); } [SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Justification = "[....]: Naming the parameter entity makes it more discoverable because it is clear what type of data should be added to this collection.")] public bool Contains(TEntity entity) { return IndexOf(entity) >= 0; } public void CopyTo(TEntity[] array, int arrayIndex) { Load(); if (entities.Count > 0) Array.Copy(entities.Items, 0, array, arrayIndex, entities.Count); } public IEnumerator GetEnumerator() { Load(); return new Enumerator(this); } internal IEnumerable GetUnderlyingValues() { return new UnderlyingValues(this); } class UnderlyingValues : IEnumerable { EntitySet entitySet; internal UnderlyingValues(EntitySet entitySet) { this.entitySet = entitySet; } public IEnumerator GetEnumerator() { return new Enumerator(this.entitySet); } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } } [SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Justification = "[....]: Naming the parameter entity makes it more discoverable because it is clear what type of data should be added to this collection.")] public int IndexOf(TEntity entity) { Load(); return entities.IndexOf(entity); } [SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "1#", Justification = "[....]: Naming the parameter entity makes it more discoverable because it is clear what type of data should be added to this collection.")] public void Insert(int index, TEntity entity) { Load(); if (index < 0 || index > Count) throw Error.ArgumentOutOfRange("index"); if (entity == null || IndexOf(entity) >= 0) throw Error.ArgumentOutOfRange("entity"); CheckModify(); entities.Insert(index, entity); OnListChanged(ListChangedType.ItemAdded, index); OnAdd(entity); } /// /// Returns true if this entity set has a deferred query /// that hasn't been executed yet. /// public bool IsDeferred { get { return HasSource; } } ////// Returns true if values have been either assigned or loaded. /// internal bool HasValues { get { return this.source == null || this.HasAssignedValues || this.HasLoadedValues; } } ////// Returns true if the entity set has been modified in any way by the user or its items /// have been loaded from the database. /// public bool HasLoadedOrAssignedValues { get { return this.HasAssignedValues || this.HasLoadedValues; } } ////// Returns true if the set has been modified in any way by the user. /// internal bool HasAssignedValues { get { return this.isModified; } } ////// Returns true if the set has been loaded from the database. /// internal bool HasLoadedValues { get { return this.isLoaded; } } ////// Returns true if the set has a deferred source query that hasn't been loaded yet. /// internal bool HasSource { get { return this.source != null && !this.HasLoadedValues; } } ////// Returns true if the collection has been loaded. /// internal bool IsLoaded { get { return this.isLoaded; } } internal IEnumerableSource { get { return this.source; } } public void Load() { if (this.HasSource) { ItemList addedEntities = entities; entities = default(ItemList ); foreach (TEntity e in source) entities.Add(e); foreach (TEntity e in addedEntities) entities.Include(e); foreach (TEntity e in removedEntities) entities.Remove(e); source = SourceState .Loaded; isLoaded = true; removedEntities = default(ItemList ); } } private void OnModified() { isModified = true; } [SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Justification = "[....]: Naming the parameter entity makes it more discoverable because it is clear what type of data should be added to this collection.")] public bool Remove(TEntity entity) { if (entity == null || entity == onRemoveEntity) return false; CheckModify(); int index = -1; bool removed = false; if (this.HasSource) { if (!removedEntities.Contains(entity)) { OnRemove(entity); // check in entities in case it has been pre-added index = entities.IndexOf(entity); if (index != -1) { entities.RemoveAt(index); } else { removedEntities.Add(entity); } removed = true; } } else { index = entities.IndexOf(entity); if (index != -1) { OnRemove(entity); entities.RemoveAt(index); removed = true; } } if (removed) { OnModified(); if (this.IsLoaded) { System.Diagnostics.Debug.Assert(index != -1); OnListChanged(ListChangedType.ItemDeleted, index); } } return removed; } public void RemoveAt(int index) { Load(); if (index < 0 || index >= Count) { throw Error.ArgumentOutOfRange("index"); } CheckModify(); TEntity entity = entities[index]; OnRemove(entity); entities.RemoveAt(index); OnModified(); OnListChanged(ListChangedType.ItemDeleted, index); } public void SetSource(IEnumerable entitySource) { if (this.HasAssignedValues || this.HasLoadedValues) throw Error.EntitySetAlreadyLoaded(); this.source = entitySource; } void CheckModify() { if (onAddEntity != null || onRemoveEntity != null) throw Error.ModifyDuringAddOrRemove(); version++; } void OnAdd(TEntity entity) { if (onAdd != null) { TEntity e = onAddEntity; onAddEntity = entity; try { onAdd(entity); } finally { onAddEntity = e; } } } void OnRemove(TEntity entity) { if (onRemove != null) { TEntity e = onRemoveEntity; onRemoveEntity = entity; try { onRemove(entity); } finally { onRemoveEntity = e; } } } class Enumerable : IEnumerable { EntitySet entitySet; public Enumerable(EntitySet entitySet) { this.entitySet = entitySet; } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } public IEnumerator GetEnumerator() { return new Enumerator(this.entitySet); } } class Enumerator : IEnumerator { EntitySet entitySet; TEntity[] items; int index; int endIndex; int version; public Enumerator(EntitySet entitySet) { this.entitySet = entitySet; this.items = entitySet.entities.Items; this.index = -1; this.endIndex = entitySet.entities.Count - 1; this.version = entitySet.version; } public void Dispose() { } public bool MoveNext() { if (version != entitySet.version) throw Error.EntitySetModifiedDuringEnumeration(); if (index == endIndex) return false; index++; return true; } public TEntity Current { get { return items[index]; } } object IEnumerator.Current { get { return items[index]; } } void IEnumerator.Reset() { if (version != entitySet.version) throw Error.EntitySetModifiedDuringEnumeration(); index = -1; } } int IList.Add(object value) { TEntity entity = value as TEntity; if (entity == null || IndexOf(entity) >= 0) { throw Error.ArgumentOutOfRange("value"); } CheckModify(); int i = entities.Count; entities.Add(entity); OnAdd(entity); return i; } bool IList.Contains(object value) { return Contains(value as TEntity); } int IList.IndexOf(object value) { return IndexOf(value as TEntity); } void IList.Insert(int index, object value) { TEntity entity = value as TEntity; if (value == null) throw Error.ArgumentOutOfRange("value"); Insert(index, entity); } bool IList.IsFixedSize { get { return false; } } bool IList.IsReadOnly { get { return false; } } void IList.Remove(object value) { Remove(value as TEntity); } object IList.this[int index] { get { return this[index]; } set { TEntity entity = value as TEntity; if (value == null) throw Error.ArgumentOutOfRange("value"); this[index] = entity; } } void ICollection.CopyTo(Array array, int index) { Load(); if (entities.Count > 0) Array.Copy(entities.Items, 0, array, index, entities.Count); } bool ICollection.IsSynchronized { get { return false; } } object ICollection.SyncRoot { get { return this; } } bool ICollection .IsReadOnly { get { return false; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } void OnListChanged(ListChangedType type, int index) { listChanged = true; if (onListChanged != null) { onListChanged(this, new ListChangedEventArgs(type, index)); } } public event ListChangedEventHandler ListChanged { add { onListChanged += value; } remove { onListChanged -= value; } } bool IListSource.ContainsListCollection { get { return true; } } private IBindingList cachedList = null; IList IListSource.GetList() { if (cachedList == null || listChanged) { cachedList = GetNewBindingList(); listChanged = false; } return cachedList; } [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification="Method doesn't represent a property of the type.")] public IBindingList GetNewBindingList() { return new EntitySetBindingList (this.ToList(), this); } } struct ItemList where T : class { T[] items; int count; public int Count { get { return count; } } public T[] Items { get { return items; } } public T this[int index] { get { return items[index]; } set { items[index] = value; } } public void Add(T item) { if (items == null || items.Length == count) GrowItems(); items[count] = item; count++; } public bool Contains(T item) { return IndexOf(item) >= 0; } public Enumerator GetEnumerator() { Enumerator e; e.items = items; e.index = -1; e.endIndex = count - 1; return e; } public bool Include(T item) { if (LastIndexOf(item) >= 0) return false; Add(item); return true; } public int IndexOf(T item) { for (int i = 0; i < count; i++) { if (items[i] == item) return i; } return -1; } public void Insert(int index, T item) { if (items == null || items.Length == count) GrowItems(); if (index < count) Array.Copy(items, index, items, index + 1, count - index); items[index] = item; count++; } public int LastIndexOf(T item) { int i = count; while (i > 0) { --i; if (items[i] == item) return i; } return -1; } public bool Remove(T item) { int i = IndexOf(item); if (i < 0) return false; RemoveAt(i); return true; } public void RemoveAt(int index) { count--; if (index < count) Array.Copy(items, index + 1, items, index, count - index); items[count] = default(T); } void GrowItems() { Array.Resize(ref items, count == 0 ? 4 : count * 2); } public struct Enumerator { internal T[] items; internal int index; internal int endIndex; public bool MoveNext() { if (index == endIndex) return false; index++; return true; } public T Current { get { return items[index]; } } } } [SuppressMessage("Microsoft.Naming", "CA1724:TypeNamesShouldNotMatchNamespaces", Justification = "[....]: The name clearly describes function and the namespace is under a DLinq namespace which will make the distinction clear.")] [DataContract] [Serializable] public sealed class Binary : IEquatable { [DataMember(Name="Bytes")] byte[] bytes; int? hashCode; public Binary(byte[] value) { if (value == null) throw Error.ArgumentNull("value"); this.bytes = new byte[value.Length]; Array.Copy(value, this.bytes, value.Length); this.ComputeHash(); } public byte[] ToArray() { byte[] copy = new byte[this.bytes.Length]; Array.Copy(this.bytes, copy, copy.Length); return copy; } public int Length { get { return this.bytes.Length; } } public static implicit operator Binary(byte[] value) { return new Binary(value); } public bool Equals(Binary other) { return this.EqualsTo(other); } public static bool operator ==(Binary binary1, Binary binary2) { if ((object)binary1 == (object)binary2) return true; if ((object)binary1 == null && (object)binary2 == null) return true; if ((object)binary1 == null || (object)binary2 == null) return false; return binary1.EqualsTo(binary2); } public static bool operator !=(Binary binary1, Binary binary2) { if ((object)binary1 == (object)binary2) return false; if ((object)binary1 == null && (object)binary2 == null) return false; if ((object)binary1 == null || (object)binary2 == null) return true; return !binary1.EqualsTo(binary2); } public override bool Equals(object obj) { return this.EqualsTo(obj as Binary); } public override int GetHashCode() { if (!hashCode.HasValue) { // hash code is not marked [DataMember], so when // using the DataContractSerializer, we'll need // to recompute the hash after deserialization. ComputeHash(); } return this.hashCode.Value; } public override string ToString() { StringBuilder sb = new StringBuilder(); sb.Append("\""); sb.Append(System.Convert.ToBase64String(this.bytes, 0, this.bytes.Length)); sb.Append("\""); return sb.ToString(); } private bool EqualsTo(Binary binary) { if ((object)this == (object)binary) return true; if ((object)binary == null) return false; if (this.bytes.Length != binary.bytes.Length) return false; if (this.hashCode != binary.hashCode) return false; for (int i = 0, n = this.bytes.Length; i < n; i++) { if (this.bytes[i] != binary.bytes[i]) return false; } return true; } /// /// Simple hash using pseudo-random coefficients for each byte in /// the array to achieve order dependency. /// private void ComputeHash() { int s = 314, t = 159; hashCode = 0; for (int i = 0; i < bytes.Length; i++) { hashCode = hashCode * s + bytes[i]; s = s * t; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq.Expressions; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Diagnostics; using System.Runtime.Serialization; using System.Diagnostics.CodeAnalysis; namespace System.Data.Linq { internal static class SourceState{ internal static readonly IEnumerable Loaded = (IEnumerable )new T[] { }; internal static readonly IEnumerable Assigned = (IEnumerable )new T[] { }; } [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification = "[....]: Types are never compared to each other. When comparisons happen it is against the entities that are represented by these constructs.")] public struct Link { T underlyingValue; IEnumerable source; public Link(T value) { this.underlyingValue = value; this.source = null; } public Link(IEnumerable source) { this.source = source; this.underlyingValue = default(T); } public Link(Link link) { this.underlyingValue = link.underlyingValue; this.source = link.source; } public bool HasValue { get { return this.source == null || this.HasLoadedValue || this.HasAssignedValue; } } public bool HasLoadedOrAssignedValue { get { return this.HasLoadedValue || this.HasAssignedValue; } } internal bool HasLoadedValue { get { return this.source == SourceState .Loaded; } } internal bool HasAssignedValue { get { return this.source == SourceState .Assigned; } } internal T UnderlyingValue { get { return this.underlyingValue; } } internal IEnumerable Source { get { return this.source; } } internal bool HasSource { get { return this.source != null && !this.HasAssignedValue && !this.HasLoadedValue; } } public T Value { get { if (this.HasSource) { this.underlyingValue = Enumerable.SingleOrDefault(this.source); this.source = SourceState .Loaded; } return this.underlyingValue; } set { this.underlyingValue = value; this.source = SourceState .Assigned; } } } [SuppressMessage("Microsoft.Performance", "CA1815:OverrideEqualsAndOperatorEqualsOnValueTypes", Justification="[....]: Types are never compared to each other. When comparisons happen it is against the entities that are represented by these constructs.")] public struct EntityRef where TEntity : class { IEnumerable source; TEntity entity; public EntityRef(TEntity entity) { this.entity = entity; this.source = SourceState .Assigned; } public EntityRef(IEnumerable source) { this.source = source; this.entity = default(TEntity); } public EntityRef(EntityRef entityRef) { this.source = entityRef.source; this.entity = entityRef.entity; } public TEntity Entity { get { if (this.HasSource) { IEnumerable src = this.source; this.entity = Enumerable.SingleOrDefault(src); this.source = SourceState .Loaded; } return this.entity; } set { this.entity = value; this.source = SourceState .Assigned; } } public bool HasLoadedOrAssignedValue { get { return this.HasLoadedValue || this.HasAssignedValue; } } internal bool HasValue { get { return this.source == null || this.HasLoadedValue || this.HasAssignedValue; } } internal bool HasLoadedValue { get { return this.source == SourceState .Loaded; } } internal bool HasAssignedValue { get { return this.source == SourceState .Assigned; } } internal bool HasSource { get { return this.source != null && !this.HasLoadedValue && !this.HasAssignedValue; } } internal IEnumerable Source { get { return this.source; } } internal TEntity UnderlyingValue { get { return this.entity; } } } [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Justification="[....]: Naming chosen to represent a different concept from a collection because it is delayed loaded.")] public sealed class EntitySet : IList, IList , IListSource where TEntity : class { IEnumerable source; ItemList entities; ItemList removedEntities; Action onAdd; Action onRemove; TEntity onAddEntity; TEntity onRemoveEntity; int version; private ListChangedEventHandler onListChanged; private bool isModified; private bool isLoaded; bool listChanged; public EntitySet() { } public EntitySet(Action onAdd, Action onRemove) { this.onAdd = onAdd; this.onRemove = onRemove; } internal EntitySet(EntitySet es, bool copyNotifications) { this.source = es.source; foreach (TEntity e in es.entities) entities.Add(e); foreach (TEntity e in es.removedEntities) removedEntities.Add(e); this.version = es.version; if (copyNotifications) { this.onAdd = es.onAdd; this.onRemove = es.onRemove; } } public int Count { get { Load(); return entities.Count; } } public TEntity this[int index] { get { Load(); if (index < 0 || index >= entities.Count) throw Error.ArgumentOutOfRange("index"); return entities[index]; } set { Load(); if (index < 0 || index >= entities.Count) throw Error.ArgumentOutOfRange("index"); if (value == null || IndexOf(value) >= 0) throw Error.ArgumentOutOfRange("value"); CheckModify(); TEntity old = entities[index]; OnRemove(old); OnListChanged(ListChangedType.ItemDeleted, index); OnAdd(value); entities[index] = value; OnModified(); OnListChanged(ListChangedType.ItemAdded, index); } } [SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Justification = "[....]: Naming the parameter entity makes it more discoverable because it is clear what type of data should be added to this collection.")] public void Add(TEntity entity) { if (entity == null) { throw Error.ArgumentNull("entity"); } if (entity != onAddEntity) { CheckModify(); if (!entities.Contains(entity)) { OnAdd(entity); if (this.HasSource) removedEntities.Remove(entity); entities.Add(entity); if (this.IsLoaded) { OnListChanged(ListChangedType.ItemAdded, IndexOf(entity)); } } OnModified(); } } public void AddRange(IEnumerable collection) { if (collection == null) throw Error.ArgumentNull("collection"); CheckModify(); // convert to List in case adding elements here removes them from the 'collection' (ie entityset to entityset assignment) collection = collection.ToList(); foreach (TEntity e in collection) { if (!entities.Contains(e)) { OnAdd(e); if (this.HasSource) removedEntities.Remove(e); entities.Add(e); if (this.IsLoaded){ OnListChanged(ListChangedType.ItemAdded, IndexOf(e)); } } } OnModified(); } public void Assign(IEnumerable entitySource) { Clear(); if (entitySource != null) AddRange(entitySource); // When an entity set is assigned, it is considered loaded. // Since with defer loading enabled, a load is triggered // anyways, this is only necessary in cases where defer loading // is disabled. In such cases, the materializer assigns a // prefetched collection and we want IsLoaded to be true. this.isLoaded = true; } public void Clear() { Load(); CheckModify(); if (entities.Items != null) { List removeList = new List (entities.Items); foreach (TEntity e in removeList) { Remove(e); } } entities = default(ItemList ); OnModified(); OnListChanged(ListChangedType.Reset, 0); } [SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Justification = "[....]: Naming the parameter entity makes it more discoverable because it is clear what type of data should be added to this collection.")] public bool Contains(TEntity entity) { return IndexOf(entity) >= 0; } public void CopyTo(TEntity[] array, int arrayIndex) { Load(); if (entities.Count > 0) Array.Copy(entities.Items, 0, array, arrayIndex, entities.Count); } public IEnumerator GetEnumerator() { Load(); return new Enumerator(this); } internal IEnumerable GetUnderlyingValues() { return new UnderlyingValues(this); } class UnderlyingValues : IEnumerable { EntitySet entitySet; internal UnderlyingValues(EntitySet entitySet) { this.entitySet = entitySet; } public IEnumerator GetEnumerator() { return new Enumerator(this.entitySet); } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } } [SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Justification = "[....]: Naming the parameter entity makes it more discoverable because it is clear what type of data should be added to this collection.")] public int IndexOf(TEntity entity) { Load(); return entities.IndexOf(entity); } [SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "1#", Justification = "[....]: Naming the parameter entity makes it more discoverable because it is clear what type of data should be added to this collection.")] public void Insert(int index, TEntity entity) { Load(); if (index < 0 || index > Count) throw Error.ArgumentOutOfRange("index"); if (entity == null || IndexOf(entity) >= 0) throw Error.ArgumentOutOfRange("entity"); CheckModify(); entities.Insert(index, entity); OnListChanged(ListChangedType.ItemAdded, index); OnAdd(entity); } /// /// Returns true if this entity set has a deferred query /// that hasn't been executed yet. /// public bool IsDeferred { get { return HasSource; } } ////// Returns true if values have been either assigned or loaded. /// internal bool HasValues { get { return this.source == null || this.HasAssignedValues || this.HasLoadedValues; } } ////// Returns true if the entity set has been modified in any way by the user or its items /// have been loaded from the database. /// public bool HasLoadedOrAssignedValues { get { return this.HasAssignedValues || this.HasLoadedValues; } } ////// Returns true if the set has been modified in any way by the user. /// internal bool HasAssignedValues { get { return this.isModified; } } ////// Returns true if the set has been loaded from the database. /// internal bool HasLoadedValues { get { return this.isLoaded; } } ////// Returns true if the set has a deferred source query that hasn't been loaded yet. /// internal bool HasSource { get { return this.source != null && !this.HasLoadedValues; } } ////// Returns true if the collection has been loaded. /// internal bool IsLoaded { get { return this.isLoaded; } } internal IEnumerableSource { get { return this.source; } } public void Load() { if (this.HasSource) { ItemList addedEntities = entities; entities = default(ItemList ); foreach (TEntity e in source) entities.Add(e); foreach (TEntity e in addedEntities) entities.Include(e); foreach (TEntity e in removedEntities) entities.Remove(e); source = SourceState .Loaded; isLoaded = true; removedEntities = default(ItemList ); } } private void OnModified() { isModified = true; } [SuppressMessage("Microsoft.Naming", "CA1725:ParameterNamesShouldMatchBaseDeclaration", MessageId = "0#", Justification = "[....]: Naming the parameter entity makes it more discoverable because it is clear what type of data should be added to this collection.")] public bool Remove(TEntity entity) { if (entity == null || entity == onRemoveEntity) return false; CheckModify(); int index = -1; bool removed = false; if (this.HasSource) { if (!removedEntities.Contains(entity)) { OnRemove(entity); // check in entities in case it has been pre-added index = entities.IndexOf(entity); if (index != -1) { entities.RemoveAt(index); } else { removedEntities.Add(entity); } removed = true; } } else { index = entities.IndexOf(entity); if (index != -1) { OnRemove(entity); entities.RemoveAt(index); removed = true; } } if (removed) { OnModified(); if (this.IsLoaded) { System.Diagnostics.Debug.Assert(index != -1); OnListChanged(ListChangedType.ItemDeleted, index); } } return removed; } public void RemoveAt(int index) { Load(); if (index < 0 || index >= Count) { throw Error.ArgumentOutOfRange("index"); } CheckModify(); TEntity entity = entities[index]; OnRemove(entity); entities.RemoveAt(index); OnModified(); OnListChanged(ListChangedType.ItemDeleted, index); } public void SetSource(IEnumerable entitySource) { if (this.HasAssignedValues || this.HasLoadedValues) throw Error.EntitySetAlreadyLoaded(); this.source = entitySource; } void CheckModify() { if (onAddEntity != null || onRemoveEntity != null) throw Error.ModifyDuringAddOrRemove(); version++; } void OnAdd(TEntity entity) { if (onAdd != null) { TEntity e = onAddEntity; onAddEntity = entity; try { onAdd(entity); } finally { onAddEntity = e; } } } void OnRemove(TEntity entity) { if (onRemove != null) { TEntity e = onRemoveEntity; onRemoveEntity = entity; try { onRemove(entity); } finally { onRemoveEntity = e; } } } class Enumerable : IEnumerable { EntitySet entitySet; public Enumerable(EntitySet entitySet) { this.entitySet = entitySet; } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } public IEnumerator GetEnumerator() { return new Enumerator(this.entitySet); } } class Enumerator : IEnumerator { EntitySet entitySet; TEntity[] items; int index; int endIndex; int version; public Enumerator(EntitySet entitySet) { this.entitySet = entitySet; this.items = entitySet.entities.Items; this.index = -1; this.endIndex = entitySet.entities.Count - 1; this.version = entitySet.version; } public void Dispose() { } public bool MoveNext() { if (version != entitySet.version) throw Error.EntitySetModifiedDuringEnumeration(); if (index == endIndex) return false; index++; return true; } public TEntity Current { get { return items[index]; } } object IEnumerator.Current { get { return items[index]; } } void IEnumerator.Reset() { if (version != entitySet.version) throw Error.EntitySetModifiedDuringEnumeration(); index = -1; } } int IList.Add(object value) { TEntity entity = value as TEntity; if (entity == null || IndexOf(entity) >= 0) { throw Error.ArgumentOutOfRange("value"); } CheckModify(); int i = entities.Count; entities.Add(entity); OnAdd(entity); return i; } bool IList.Contains(object value) { return Contains(value as TEntity); } int IList.IndexOf(object value) { return IndexOf(value as TEntity); } void IList.Insert(int index, object value) { TEntity entity = value as TEntity; if (value == null) throw Error.ArgumentOutOfRange("value"); Insert(index, entity); } bool IList.IsFixedSize { get { return false; } } bool IList.IsReadOnly { get { return false; } } void IList.Remove(object value) { Remove(value as TEntity); } object IList.this[int index] { get { return this[index]; } set { TEntity entity = value as TEntity; if (value == null) throw Error.ArgumentOutOfRange("value"); this[index] = entity; } } void ICollection.CopyTo(Array array, int index) { Load(); if (entities.Count > 0) Array.Copy(entities.Items, 0, array, index, entities.Count); } bool ICollection.IsSynchronized { get { return false; } } object ICollection.SyncRoot { get { return this; } } bool ICollection .IsReadOnly { get { return false; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } void OnListChanged(ListChangedType type, int index) { listChanged = true; if (onListChanged != null) { onListChanged(this, new ListChangedEventArgs(type, index)); } } public event ListChangedEventHandler ListChanged { add { onListChanged += value; } remove { onListChanged -= value; } } bool IListSource.ContainsListCollection { get { return true; } } private IBindingList cachedList = null; IList IListSource.GetList() { if (cachedList == null || listChanged) { cachedList = GetNewBindingList(); listChanged = false; } return cachedList; } [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification="Method doesn't represent a property of the type.")] public IBindingList GetNewBindingList() { return new EntitySetBindingList (this.ToList(), this); } } struct ItemList where T : class { T[] items; int count; public int Count { get { return count; } } public T[] Items { get { return items; } } public T this[int index] { get { return items[index]; } set { items[index] = value; } } public void Add(T item) { if (items == null || items.Length == count) GrowItems(); items[count] = item; count++; } public bool Contains(T item) { return IndexOf(item) >= 0; } public Enumerator GetEnumerator() { Enumerator e; e.items = items; e.index = -1; e.endIndex = count - 1; return e; } public bool Include(T item) { if (LastIndexOf(item) >= 0) return false; Add(item); return true; } public int IndexOf(T item) { for (int i = 0; i < count; i++) { if (items[i] == item) return i; } return -1; } public void Insert(int index, T item) { if (items == null || items.Length == count) GrowItems(); if (index < count) Array.Copy(items, index, items, index + 1, count - index); items[index] = item; count++; } public int LastIndexOf(T item) { int i = count; while (i > 0) { --i; if (items[i] == item) return i; } return -1; } public bool Remove(T item) { int i = IndexOf(item); if (i < 0) return false; RemoveAt(i); return true; } public void RemoveAt(int index) { count--; if (index < count) Array.Copy(items, index + 1, items, index, count - index); items[count] = default(T); } void GrowItems() { Array.Resize(ref items, count == 0 ? 4 : count * 2); } public struct Enumerator { internal T[] items; internal int index; internal int endIndex; public bool MoveNext() { if (index == endIndex) return false; index++; return true; } public T Current { get { return items[index]; } } } } [SuppressMessage("Microsoft.Naming", "CA1724:TypeNamesShouldNotMatchNamespaces", Justification = "[....]: The name clearly describes function and the namespace is under a DLinq namespace which will make the distinction clear.")] [DataContract] [Serializable] public sealed class Binary : IEquatable { [DataMember(Name="Bytes")] byte[] bytes; int? hashCode; public Binary(byte[] value) { if (value == null) throw Error.ArgumentNull("value"); this.bytes = new byte[value.Length]; Array.Copy(value, this.bytes, value.Length); this.ComputeHash(); } public byte[] ToArray() { byte[] copy = new byte[this.bytes.Length]; Array.Copy(this.bytes, copy, copy.Length); return copy; } public int Length { get { return this.bytes.Length; } } public static implicit operator Binary(byte[] value) { return new Binary(value); } public bool Equals(Binary other) { return this.EqualsTo(other); } public static bool operator ==(Binary binary1, Binary binary2) { if ((object)binary1 == (object)binary2) return true; if ((object)binary1 == null && (object)binary2 == null) return true; if ((object)binary1 == null || (object)binary2 == null) return false; return binary1.EqualsTo(binary2); } public static bool operator !=(Binary binary1, Binary binary2) { if ((object)binary1 == (object)binary2) return false; if ((object)binary1 == null && (object)binary2 == null) return false; if ((object)binary1 == null || (object)binary2 == null) return true; return !binary1.EqualsTo(binary2); } public override bool Equals(object obj) { return this.EqualsTo(obj as Binary); } public override int GetHashCode() { if (!hashCode.HasValue) { // hash code is not marked [DataMember], so when // using the DataContractSerializer, we'll need // to recompute the hash after deserialization. ComputeHash(); } return this.hashCode.Value; } public override string ToString() { StringBuilder sb = new StringBuilder(); sb.Append("\""); sb.Append(System.Convert.ToBase64String(this.bytes, 0, this.bytes.Length)); sb.Append("\""); return sb.ToString(); } private bool EqualsTo(Binary binary) { if ((object)this == (object)binary) return true; if ((object)binary == null) return false; if (this.bytes.Length != binary.bytes.Length) return false; if (this.hashCode != binary.hashCode) return false; for (int i = 0, n = this.bytes.Length; i < n; i++) { if (this.bytes[i] != binary.bytes[i]) return false; } return true; } /// /// Simple hash using pseudo-random coefficients for each byte in /// the array to achieve order dependency. /// private void ComputeHash() { int s = 314, t = 159; hashCode = 0; for (int i = 0; i < bytes.Length; i++) { hashCode = hashCode * s + bytes[i]; s = s * t; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- PrivateUnsafeNativeCompoundFileMethods.cs
- KerberosTicketHashIdentifierClause.cs
- GrammarBuilderWildcard.cs
- SessionStateSection.cs
- HitTestResult.cs
- VirtualPath.cs
- EntryPointNotFoundException.cs
- AdjustableArrowCap.cs
- X509CertificateCollection.cs
- UIInitializationException.cs
- NetCodeGroup.cs
- StatusBarDrawItemEvent.cs
- DataGridViewAccessibleObject.cs
- IResourceProvider.cs
- UxThemeWrapper.cs
- LoginCancelEventArgs.cs
- securestring.cs
- TextEditorContextMenu.cs
- Int64KeyFrameCollection.cs
- CodeGotoStatement.cs
- ReferenceConverter.cs
- CalculatedColumn.cs
- AnnotationStore.cs
- FocusWithinProperty.cs
- CounterSampleCalculator.cs
- Rotation3D.cs
- NetSectionGroup.cs
- KeyboardEventArgs.cs
- CodeTryCatchFinallyStatement.cs
- SecurityTokenRequirement.cs
- PrintPreviewDialog.cs
- ImageAttributes.cs
- DefaultValidator.cs
- EventSetter.cs
- IConvertible.cs
- ImpersonateTokenRef.cs
- SQLInt16Storage.cs
- FileLevelControlBuilderAttribute.cs
- ToolStripDesignerAvailabilityAttribute.cs
- TransactedBatchingBehavior.cs
- AggregateException.cs
- RIPEMD160Managed.cs
- RunClient.cs
- DataGridViewCellContextMenuStripNeededEventArgs.cs
- CursorConverter.cs
- HttpCachePolicy.cs
- AvTraceDetails.cs
- StatusBarItem.cs
- PngBitmapDecoder.cs
- AppDomain.cs
- LogRecordSequence.cs
- DataObject.cs
- DropSource.cs
- HelloMessageApril2005.cs
- HierarchicalDataBoundControl.cs
- WebBrowserSiteBase.cs
- DataGridTextColumn.cs
- RequestResizeEvent.cs
- CommandField.cs
- TextSelectionProcessor.cs
- NaturalLanguageHyphenator.cs
- GeneralTransformCollection.cs
- Pair.cs
- ExtendedPropertyDescriptor.cs
- StyleCollectionEditor.cs
- GridViewEditEventArgs.cs
- DependencyProperty.cs
- SQLMoneyStorage.cs
- AttributeUsageAttribute.cs
- UserNameSecurityToken.cs
- Point3D.cs
- SrgsToken.cs
- ProviderSettings.cs
- EdmScalarPropertyAttribute.cs
- MetricEntry.cs
- SHA1CryptoServiceProvider.cs
- ChangeBlockUndoRecord.cs
- FigureParagraph.cs
- WindowClosedEventArgs.cs
- SqlNodeAnnotations.cs
- bidPrivateBase.cs
- PrintDialogException.cs
- ViewStateException.cs
- DebuggerAttributes.cs
- PersonalizationProviderCollection.cs
- SponsorHelper.cs
- ListBindingConverter.cs
- RtfToken.cs
- SessionEndedEventArgs.cs
- EmptyEnumerable.cs
- SystemDiagnosticsSection.cs
- RowVisual.cs
- TextBox.cs
- ToolStripContextMenu.cs
- Int32KeyFrameCollection.cs
- OutputCacheSection.cs
- XmlChildNodes.cs
- DesignerForm.cs
- SqlBooleanizer.cs
- SqlProvider.cs