<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ include file="EF.Utility.CS.ttinclude"#><#@
output extension=".cs"#><#
CodeGenerationTools code = new CodeGenerationTools(this);
MetadataLoader loader = new MetadataLoader(this);
CodeRegion region = new CodeRegion(this, 1);
MetadataTools ef = new MetadataTools(this);
string inputFile = @"SchoolModel.edmx";
EdmItemCollection ItemCollection = loader.CreateEdmItemCollection(inputFile);
string namespaceName = code.EscapeNamespace(@"SchoolSample.EntityModel");
string codeForSilverlight = @"None";
string codeForWPF = @"WPF4";
string codeForIEditableObject = @"true";
EntityFrameworkTemplateFileManager fileManager = EntityFrameworkTemplateFileManager.Create(this);
WriteHeader(fileManager);
#>
#if (SILVERLIGHT || WPF)
<#
BeginNamespace(namespaceName, code);
WriteNotifyValidationResultChanged();
WriteClientChangeTracking();
EndNamespace(namespaceName);
#>
#endif
<#
// Emit Entity Types
foreach (EntityType entity in ItemCollection.GetItems<EntityType>().OrderBy(e => e.Name))
{
if (codeForSilverlight == @"Silverlight4")
{
fileManager.StartNewFile("SL4." + entity.Name + ".cs");
#>
#if SILVERLIGHT
<#
BeginNamespace(namespaceName, code);
#>
<#=Accessibility.ForType(entity)#> <#=code.SpaceAfter(code.AbstractOption(entity))#>partial class <#=code.Escape(entity)#><#=code.StringBefore(" : ", code.Escape(entity.BaseType))#><#=entity.BaseType == null ? " : " : ", "#>IClientChangeTracking, IChangeTracking, IRevertibleChangeTracking, INotifyDataErrorInfo<#=codeForIEditableObject == "true" ? ", IEditableObject" : "" #>
{
<#
region.Begin("IClientChangeTracking Interface");
WriteAcceptChangesAndRejectChanges();
if (entity.BaseType == null)
{
WriteHasChangesProperty();
}
#>
/// <summary>
/// Accepts changes for the entity object and all objects of its object graph
/// </summary>
public <#=entity.BaseType == null ? "virtual " : "override " #>void AcceptObjectGraphChanges()
{
this.AcceptChanges();
<#
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
// call AccetChanges() on all Navigation properties
<#
}
foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
{
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
foreach (var item in <#=code.Escape(navProperty)#>)
item.AcceptChanges();
<#
}
else
{
#>
if (<#=code.Escape(navProperty)#> != null)
<#=code.Escape(navProperty)#>.AcceptChanges();
<#
}
}
if (entity.BaseType != null)
{
#>
// call base AcceptObjectGraphChanges()
base.AcceptObjectGraphChanges();
<#
}
#>
}
/// <summary>
/// Rejects changes made to the entity object and all objects of its object graph
/// </summary>
public <#=entity.BaseType == null ? "virtual " : "override " #>void RejectObjectGraphChanges()
{
this.RejectChanges();
<#
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
// call RejectChanges() on all Navigation properties
<#
}
foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
{
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
foreach (var item in <#=code.Escape(navProperty)#>)
item.RejectChanges();
<#
}
else
{
#>
if (<#=code.Escape(navProperty)#> != null)
<#=code.Escape(navProperty)#>.RejectChanges();
<#
}
}
if (entity.BaseType != null)
{
#>
// call base RejectObjectGraphChanges()
base.RejectObjectGraphChanges();
<#
}
#>
}
<#
if (entity.BaseType == null)
{
#>
/// <summary>
/// Returns whether the entity object along with its object graph has any changes
/// </summary>
public bool ObjectGraphHasChanges()
{
return ObjectGraphHasChanges(new List<object>());
}
internal virtual bool ObjectGraphHasChanges(List<object> objectList)
{
// if already visited this object, just return false
if (objectList.Any(n => ReferenceEquals(n, this))) return false;
var hasChanges = HasChanges;
if (hasChanges) return true;
<#
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
// if not, add itself to the visited graph
var visitedGraph = objectList.ToList();
visitedGraph.Add(this);
// call ObjectGraphHasChanges() on all Navigation properties
<#
}
foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
{
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
foreach (var item in <#=code.Escape(navProperty)#>)
{
hasChanges = item.ObjectGraphHasChanges(visitedGraph);
if (hasChanges) return true;
}
<#
}
else
{
#>
if (<#=code.Escape(navProperty)#> != null)
{
hasChanges = <#=code.Escape(navProperty)#>.ObjectGraphHasChanges(visitedGraph);
if (hasChanges) return true;
}
<#
}
}
#>
return false;
}
<#
}
else
{
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
internal override bool ObjectGraphHasChanges(List<object> objectList)
{
// if already visited this object, just return false
if (objectList.Any(n => ReferenceEquals(n, this))) return false;
bool hasChanges = base.ObjectGraphHasChanges(objectList);
if (hasChanges) return true;
// if not, add itself to the visited graph
var visitedGraph = objectList.ToList();
visitedGraph.Add(this);
// call ObjectGraphHasChanges() on all Navigation properties
<#
foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
{
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
foreach (var item in <#=code.Escape(navProperty)#>)
{
hasChanges = item.ObjectGraphHasChanges(visitedGraph);
if (hasChanges) return true;
}
<#
}
else
{
#>
if (<#=code.Escape(navProperty)#> != null)
{
hasChanges = <#=code.Escape(navProperty)#>.ObjectGraphHasChanges(visitedGraph);
if (hasChanges) return true;
}
<#
}
}
#>
return false;
}
<#
}
}
if (entity.BaseType == null)
{
#>
/// <summary>
/// Returns the estimate size of the entity object along with its object graph
/// </summary>
public long EstimateObjectGraphSize()
{
long size = 0;
var visitedGraph = new List<object>();
EstimateObjectGraphSize(ref size, ref visitedGraph);
return size;
}
<#
}
#>
internal <#=entity.BaseType == null ? "virtual " : "override " #>void EstimateObjectGraphSize(ref long size, ref List<object> visitedGraph)
{
// if already visited this object, just return
if (visitedGraph.Any(n => ReferenceEquals(n, this))) return;
<#
if (entity.BaseType != null)
{
#>
// call base EstimateObjectGraphSize()
base.EstimateObjectGraphSize(ref size, ref visitedGraph);
<#
}
#>
size += EstimateSize;
if (visitedGraph.All(i => !ReferenceEquals(i, this))) visitedGraph.Add(this);
<#
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
// call EstimateObjectGraphSize() on all Navigation properties
<#
}
foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
{
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
foreach (var item in <#=code.Escape(navProperty)#>)
{
item.EstimateObjectGraphSize(ref size, ref visitedGraph);
}
<#
}
else
{
#>
if (<#=code.Escape(navProperty)#> != null)
{
<#=code.Escape(navProperty)#>.EstimateObjectGraphSize(ref size, ref visitedGraph);
}
<#
}
}
#>
}
<#
if (entity.BaseType == null)
{
#>
/// <summary>
/// Returns the estimate size of the optimized entity object graph
/// with only objects that have changes
/// </summary>
public long EstimateObjectGraphChangeSize()
{
long size = 0;
if (!ObjectGraphHasChanges()) return size;
var visitedGraph = new List<object> {this};
EstimateObjectGraphChangeSize(ref size, visitedGraph);
return size;
}
<#
}
#>
internal <#=entity.BaseType == null ? "virtual " : "override " #>void EstimateObjectGraphChangeSize(ref long size, List<object> objectList)
{
<#
if (entity.BaseType != null)
{
#>
// call base EstimateObjectGraphChangeSize()
base.EstimateObjectGraphChangeSize(ref size, objectList);
<#
}
#>
size += EstimateSize;
<#
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
// call EstimateObjectGraphChangeSize() on all Navigation properties that has change
<#
}
foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
{
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
foreach (var n in <#=code.Escape(navProperty)#>)
{
// if n has already been visited, we need to skip it
if (objectList.All(i => !ReferenceEquals(i, n)))
{
if (ChangeTracker.ObjectsAddedToCollectionProperties.ContainsKey("<#=code.Escape(navProperty)#>")
&& ChangeTracker.ObjectsAddedToCollectionProperties["<#=code.Escape(navProperty)#>"].Contains(n))
{
// if n exists in ObjectsAddedToCollectionProperties, we need to add its size
var visitedGraph = objectList.ToList();
visitedGraph.Add(n);
n.EstimateObjectGraphChangeSize(ref size, visitedGraph);
}
else if (n.ObjectGraphHasChanges(objectList))
{
// if n has changes, we also need to add its size
var visitedGraph = objectList.ToList();
visitedGraph.Add(n);
n.EstimateObjectGraphChangeSize(ref size, visitedGraph);
}
}
}
<#
}
else
{
#>
// if <#=code.Escape(navProperty)#> has already been visited, we need to skip it
if (<#=code.Escape(navProperty)#> != null && objectList.All(i => !ReferenceEquals(i, <#=code.Escape(navProperty)#>)))
{
if (<#=code.Escape(navProperty)#>.ObjectGraphHasChanges(objectList))
{
var visitedGraph = objectList.ToList();
visitedGraph.Add(<#=code.Escape(navProperty)#>);
<#=code.Escape(navProperty)#>.EstimateObjectGraphChangeSize(ref size, visitedGraph);
}
}
<#
}
}
#>
}
<#
if (entity.BaseType == null)
{
#>
/// <summary>
/// Returns an optimized entity object graph with only objects that have changes
/// </summary>
public IObjectWithChangeTracker GetObjectGraphChanges()
{
if (!ObjectGraphHasChanges()) return null;
var item = this.Clone();
var visitedGraph = new List<object> { item };
// loop through all navigation properties and trim any unchanged items
item.TrimUnchangedEntities(visitedGraph);
return item;
}
internal virtual void TrimUnchangedEntities(List<object> objectList)
{
<#
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
bool changeTrackingEnabled = ChangeTracker.ChangeTrackingEnabled;
this.StopTracking();
// trim all navigation property items that do not have any change
<#
}
foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
{
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
foreach (var n in <#=code.Escape(navProperty)#>.ToList())
{
// if n has already been visited, we need to skip it
if (objectList.All(i => !ReferenceEquals(i, n)))
{
if (ChangeTracker.ObjectsAddedToCollectionProperties.ContainsKey("<#=code.Escape(navProperty)#>")
&& ChangeTracker.ObjectsAddedToCollectionProperties["<#=code.Escape(navProperty)#>"].Contains(n))
{
// if n exists in ObjectsAddedToCollectionProperties, we need to keep it
var visitedGraph = objectList.ToList();
visitedGraph.Add(n);
n.TrimUnchangedEntities(visitedGraph);
}
else if (n.ObjectGraphHasChanges(objectList))
{
// if n has changes, we also need to keep it
var visitedGraph = objectList.ToList();
visitedGraph.Add(n);
n.TrimUnchangedEntities(visitedGraph);
}
else
{
<#=code.Escape(navProperty)#>.Remove(n);
}
}
}
<#
}
else
{
#>
// if <#=code.Escape(navProperty)#> has already been visited, we need to skip it
if (<#=code.Escape(navProperty)#> != null && objectList.All(i => !ReferenceEquals(i, <#=code.Escape(navProperty)#>)))
{
if (<#=code.Escape(navProperty)#>.ObjectGraphHasChanges(objectList))
{
var visitedGraph = objectList.ToList();
visitedGraph.Add(<#=code.Escape(navProperty)#>);
<#=code.Escape(navProperty)#>.TrimUnchangedEntities(visitedGraph);
}
else
{
<#=code.Escape(navProperty)#> = null;
}
}
<#
}
}
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
ChangeTracker.ChangeTrackingEnabled = changeTrackingEnabled;
<#
}
#>
}
<#
}
else
{
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
internal override void TrimUnchangedEntities(List<object> objectList)
{
// call base TrimUnchangedEntities() first
base.TrimUnchangedEntities(objectList);
bool changeTrackingEnabled = ChangeTracker.ChangeTrackingEnabled;
this.StopTracking();
// trim all navigation property items that do not have any change
<#
foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
{
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
foreach (var n in <#=code.Escape(navProperty)#>.ToList())
{
// if n has already been visited, we need to skip it
if (objectList.All(i => !ReferenceEquals(i, n)))
{
if (ChangeTracker.ObjectsAddedToCollectionProperties.ContainsKey("<#=code.Escape(navProperty)#>")
&& ChangeTracker.ObjectsAddedToCollectionProperties["<#=code.Escape(navProperty)#>"].Contains(n))
{
// if n exists in ObjectsAddedToCollectionProperties, we need to keep it
var visitedGraph = objectList.ToList();
visitedGraph.Add(n);
n.TrimUnchangedEntities(visitedGraph);
}
else if (n.ObjectGraphHasChanges(objectList))
{
// if n has changes, we also need to keep it
var visitedGraph = objectList.ToList();
visitedGraph.Add(n);
n.TrimUnchangedEntities(visitedGraph);
}
else
{
<#=code.Escape(navProperty)#>.Remove(n);
}
}
}
<#
}
else
{
#>
// if <#=code.Escape(navProperty)#> has already been visited, we need to skip it
if (<#=code.Escape(navProperty)#> != null && objectList.All(i => !ReferenceEquals(i, <#=code.Escape(navProperty)#>)))
{
if (<#=code.Escape(navProperty)#>.ObjectGraphHasChanges(objectList))
{
var visitedGraph = objectList.ToList();
visitedGraph.Add(<#=code.Escape(navProperty)#>);
<#=code.Escape(navProperty)#>.TrimUnchangedEntities(visitedGraph);
}
else
{
<#=code.Escape(navProperty)#> = null;
}
}
<#
}
}
#>
ChangeTracker.ChangeTrackingEnabled = changeTrackingEnabled;
}
<#
}
}
region.End();
region.Begin("IClientChangeTracking Helper Property");
#>
internal <#=entity.BaseType == null ? "virtual " : "override " #>long EstimateSize
{
get
{
long _size = 0;
<#
if (entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity).Count() > 0)
{
#>
// estimate size of all Primitive Properties
<#
}
foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity))
{
switch (((PrimitiveType)edmProperty.TypeUsage.EdmType).PrimitiveTypeKind)
{
case PrimitiveTypeKind.Binary:
#>
if (<#=code.Escape(edmProperty)#> != null)
_size += <#=code.Escape(edmProperty)#>.Length * sizeof (Byte); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Boolean:
#>
_size += sizeof(Boolean); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Byte:
#>
_size += sizeof(Byte); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.DateTime:
#>
_size += sizeof(ulong); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.DateTimeOffset:
#>
_size += sizeof(ulong) + sizeof(short); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Decimal:
#>
_size += sizeof(Decimal); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Double:
#>
_size += sizeof(Double); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Guid:
#>
_size += sizeof(int) + sizeof(short) * 2 + sizeof(byte) * 8; // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Int16:
#>
_size += sizeof(Int16); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Int32:
#>
_size += sizeof(Int32); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Int64:
#>
_size += sizeof(Int64); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.SByte:
#>
_size += sizeof(SByte); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Single:
#>
_size += sizeof(Single); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.String:
#>
if (<#=code.Escape(edmProperty)#> != null)
_size += <#=code.Escape(edmProperty)#>.Length * sizeof(char); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Time:
#>
_size += sizeof(long); // <#=code.Escape(edmProperty)#>
<#
break;
}
}
if (entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity).Count() > 0)
{
#>
// get EstimateSize of all Complex Properties
<#
}
foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity))
{
#>
if (<#=code.Escape(edmProperty)#> != null)
_size += <#=code.Escape(edmProperty)#>.EstimateSize; // <#=code.Escape(edmProperty)#>
<#
}
#>
return _size;
}
}
<#
region.End();
region.Begin("IChangeTracking and IRevertibleChangeTracking interfaces");
WriteIRevertibleChangeTrackingInterface();
region.End();
region.Begin("INotifyDataErrorInfo interface");
WriteINotifyDataErrorInfoInterfaceForEntityType(entity);
region.End();
region.Begin("INotifyDataErrorInfo Protected & Private Helper Methods");
if (entity.BaseType == null)
{
#>
/// <summary>
/// Declares a new error for the property name provided, or the entity if
/// propertyName is String.Empty/null.
/// </summary>
protected void AddError(string propertyName, ValidationResult validationResult)
{
if (validationResult == null)
{
throw new ArgumentNullException("validationResult");
}
if (propertyName == null)
{
propertyName = string.Empty;
}
List<ValidationResult> errors;
if (!ValidationErrors.ContainsKey(propertyName))
{
errors = new List<ValidationResult>();
ValidationErrors.Add(propertyName, errors);
}
else
{
errors = ValidationErrors[propertyName];
}
// search for duplicate error message with the same propertyName
var foundError = errors.Where(n =>
n.ErrorMessage == validationResult.ErrorMessage).FirstOrDefault();
if (foundError == null)
{
errors.Insert(0, validationResult);
RaiseErrorsChanged(propertyName);
}
}
/// <summary>
/// Removes one specific error for the provided property name.
/// </summary>
/// <param name="propertyName"></param>
/// <param name="validationResult"></param>
protected void RemoveError(string propertyName, ValidationResult validationResult)
{
if (validationResult == null)
{
throw new ArgumentNullException("validationResult");
}
if (propertyName == null)
{
propertyName = string.Empty;
}
List<ValidationResult> errors;
if (ValidationErrors.ContainsKey(propertyName))
{
errors = ValidationErrors[propertyName];
// search for the error message that need to be removed
var foundError = errors.Where(n =>
n.ErrorMessage == validationResult.ErrorMessage).FirstOrDefault();
if (foundError != null)
{
errors.Remove(foundError);
if (errors.Count == 0)
{
// This entity no longer exposes errors for this property name.
ValidationErrors.Remove(propertyName);
}
RaiseErrorsChanged(propertyName);
}
}
}
/// <summary>
/// Removes the known errors from the cache, for the provided property name.
/// </summary>
/// <param name="propertyName">Propery name or String.Empty/null for top-level errors</param>
protected void ClearErrors(string propertyName)
{
if (propertyName == null)
{
propertyName = string.Empty;
}
if (ValidationErrors.ContainsKey(propertyName))
{
// This entity no longer exposes errors for this property name.
ValidationErrors.Remove(propertyName);
RaiseErrorsChanged(propertyName);
}
}
/// <summary>
/// Removes the known errors for all property names.
/// </summary>
protected void ClearErrors()
{
foreach (string propertyName in ValidationErrors.Keys.ToList())
{
// This entity no longer exposes errors for this property name.
ValidationErrors.Remove(propertyName);
RaiseErrorsChanged(propertyName);
}
}
/// <summary>
/// Gets a value indicating whether or not top-level validation rules
/// must be applied whenever any entity property changes.
/// </summary>
protected static Boolean ValidateEntityOnPropertyChanged;
<#
}
#>
/// <summary>
/// Removes any known errors for the provided property name
/// by calling ClearErrors()
/// </summary>
/// <param name="propertyName">Propery name or String.Empty/null for top-level errors</param>
partial void PropertySetterEntry(string propertyName)
{
if (IsDeserializing)
{
return;
}
if (ValidateEntityOnPropertyChanged)
{
ClearErrors();
}
else
{
ClearErrors(propertyName);
}
}
/// <summary>
/// Validates for any known errors for the provided property name
/// </summary>
/// <param name="propertyName">Propery name or String.Empty/null for top-level errors</param>
/// <param name="propertyValue">Property value</param>
partial void PropertySetterExit(string propertyName, object propertyValue)
{
if (IsDeserializing)
{
return;
}
if (ValidateEntityOnPropertyChanged)
{
Validate(string.Empty, this);
}
else
{
Validate(propertyName, propertyValue);
}
}
<#
foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity))
{
#>
// Synchronize validation error changes from Complex Type property
private void Handle<#=edmProperty.Name#>ValidationResultChanged(object sender, ValidationResultChangedEventArgs e)
{
string propertyName;
if (string.IsNullOrEmpty(e.PropertyName))
propertyName = "<#=edmProperty.Name#>";
else
propertyName = "<#=edmProperty.Name#>." + e.PropertyName;
foreach (ValidationResult item in e.AddedItems)
{
AddError(propertyName, item);
}
foreach (ValidationResult item in e.RemovedItems)
{
RemoveError(propertyName, item);
}
}
<#
}
region.End();
region.Begin("IEditableObject interface");
if (codeForIEditableObject == "true")
{
#>
private Dictionary<string , object> _cache;
public <#=entity.BaseType == null ? "virtual " : "override " #>void BeginEdit()
{
<#
if (entity.BaseType != null)
{
#>
// call base BeginEdit() first
base.BeginEdit();
<#
}
#>
if (_cache == null) _cache = new Dictionary<string, object>();
<#
if (entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity).Count() > 0)
{
#>
// copy all Primitive Properties except the primary key fields
<#
}
foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity))
{
if (!ef.IsKey(edmProperty))
{
#>
_cache["<#=code.Escape(edmProperty)#>"] = <#=code.Escape(edmProperty)#>;
<#
}
}
if (entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity).Count() > 0)
{
#>
// call BeginEdit() on all Complex Properties
<#
}
foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity))
{
#>
((IEditableObject)<#=code.Escape(edmProperty)#>).BeginEdit();
<#
}
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
// copy all Navigation Properties
<#
}
foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
{
#>
_cache["<#=code.Escape(navProperty)#>"] = <#=code.Escape(navProperty)#>;
<#
}
if (entity.BaseType == null)
{
#>
// copy ChangeTracker
_cache["ChangeTracker"] = ChangeTracker.Clone();
<#
}
#>
}
public <#=entity.BaseType == null ? "virtual " : "override " #>void CancelEdit()
{
<#
if (entity.BaseType != null)
{
#>
// call base CancelEdit() first
base.CancelEdit();
<#
}
#>
if (_cache == null) _cache = new Dictionary<string, object>();
if (_cache.Count == 0) return;
bool changeTrackingEnabled = ChangeTracker.ChangeTrackingEnabled;
this.StopTracking();
<#
if (entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity).Count() > 0)
{
#>
// copy all Primitive Properties except the primary key fields
<#
}
foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity))
{
if (!ef.IsKey(edmProperty))
{
if (((PrimitiveType)edmProperty.TypeUsage.EdmType).PrimitiveTypeKind == PrimitiveTypeKind.Binary &&
entity.NavigationProperties.Where(np=>np.GetDependentProperties().Contains(edmProperty)).Any())
{
#>
if (!EqualityComparer.BinaryEquals(<#=code.Escape(edmProperty)#>, (<#=code.Escape(edmProperty.TypeUsage)#>)_cache["<#=code.Escape(edmProperty)#>"]))
<#
}
else
{
#>
if (<#=code.Escape(edmProperty)#> != (<#=code.Escape(edmProperty.TypeUsage)#>)_cache["<#=code.Escape(edmProperty)#>"])
<#
}
#>
<#=code.Escape(edmProperty)#> = (<#=code.Escape(edmProperty.TypeUsage)#>)_cache["<#=code.Escape(edmProperty)#>"];
else
OnPropertyChanged("<#=edmProperty.Name#>");
<#
}
}
if (entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity).Count() > 0)
{
#>
// call CancelEdit() on all Complex Properties
<#
}
foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity))
{
#>
((IEditableObject)<#=code.Escape(edmProperty)#>).CancelEdit();
<#
}
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
// copy all Navigation Properties
<#
}
foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
{
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
<#=code.Escape(navProperty)#> = (TrackableCollection<<#=code.Escape(navProperty.ToEndMember.GetEntityType())#>>)_cache["<#=code.Escape(navProperty)#>"];
<#
}
else
{
#>
<#=code.Escape(navProperty)#> = (<#=code.Escape(navProperty.ToEndMember.GetEntityType())#>)_cache["<#=code.Escape(navProperty)#>"];
<#
}
}
if (entity.BaseType == null)
{
#>
// copy ChangeTracker
ChangeTracker = (ObjectChangeTracker)_cache["ChangeTracker"];
<#
}
#>
ChangeTracker.ChangeTrackingEnabled = changeTrackingEnabled;
_cache.Clear();
}
public <#=entity.BaseType == null ? "virtual " : "override " #>void EndEdit()
{
<#
if (entity.BaseType != null)
{
#>
// call base EndEdit() first
base.EndEdit();
<#
}
#>
if (_cache == null) _cache = new Dictionary<string, object>();
_cache.Clear();
<#
if (entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity).Count() > 0)
{
#>
// call EndEdit() on all Complex Properties
<#
}
foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity))
{
#>
((IEditableObject)<#=code.Escape(edmProperty)#>).EndEdit();
<#
}
#>
}
<#
}
region.End();
#>
}
<#
EndNamespace(namespaceName);
#>
#endif
<#
}
if (codeForWPF == @"WPF4")
{
fileManager.StartNewFile("WPF4." + entity.Name + ".cs");
#>
#if WPF
<#
BeginNamespace(namespaceName, code);
#>
<#=Accessibility.ForType(entity)#> <#=code.SpaceAfter(code.AbstractOption(entity))#>partial class <#=code.Escape(entity)#><#=code.StringBefore(" : ", code.Escape(entity.BaseType))#><#=entity.BaseType == null ? " : " : ", "#>IClientChangeTracking, IChangeTracking, IRevertibleChangeTracking, IDataErrorInfo<#=codeForIEditableObject == "true" ? ", IEditableObject" : "" #>
{
<#
region.Begin("IClientChangeTracking Interface");
WriteAcceptChangesAndRejectChanges();
if (entity.BaseType == null)
{
WriteHasChangesProperty();
}
#>
/// <summary>
/// Accepts changes for the entity object and all objects of its object graph
/// </summary>
public <#=entity.BaseType == null ? "virtual " : "override " #>void AcceptObjectGraphChanges()
{
this.AcceptChanges();
<#
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
// call AccetChanges() on all Navigation properties
<#
}
foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
{
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
foreach (var item in <#=code.Escape(navProperty)#>)
item.AcceptChanges();
<#
}
else
{
#>
if (<#=code.Escape(navProperty)#> != null)
<#=code.Escape(navProperty)#>.AcceptChanges();
<#
}
}
if (entity.BaseType != null)
{
#>
// call base AcceptObjectGraphChanges()
base.AcceptObjectGraphChanges();
<#
}
#>
}
/// <summary>
/// Rejects changes made to the entity object and all objects of its object graph
/// </summary>
public <#=entity.BaseType == null ? "virtual " : "override " #>void RejectObjectGraphChanges()
{
this.RejectChanges();
<#
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
// call RejectChanges() on all Navigation properties
<#
}
foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
{
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
foreach (var item in <#=code.Escape(navProperty)#>)
item.RejectChanges();
<#
}
else
{
#>
if (<#=code.Escape(navProperty)#> != null)
<#=code.Escape(navProperty)#>.RejectChanges();
<#
}
}
if (entity.BaseType != null)
{
#>
// call base RejectObjectGraphChanges()
base.RejectObjectGraphChanges();
<#
}
#>
}
<#
if (entity.BaseType == null)
{
#>
/// <summary>
/// Returns whether the entity object along with its object graph has any changes
/// </summary>
public bool ObjectGraphHasChanges()
{
return ObjectGraphHasChanges(new List<object>());
}
internal virtual bool ObjectGraphHasChanges(List<object> objectList)
{
// if already visited this object, just return false
if (objectList.Any(n => ReferenceEquals(n, this))) return false;
var hasChanges = HasChanges;
if (hasChanges) return true;
<#
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
// if not, add itself to the visited graph
var visitedGraph = objectList.ToList();
visitedGraph.Add(this);
// call ObjectGraphHasChanges() on all Navigation properties
<#
}
foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
{
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
foreach (var item in <#=code.Escape(navProperty)#>)
{
hasChanges = item.ObjectGraphHasChanges(visitedGraph);
if (hasChanges) return true;
}
<#
}
else
{
#>
if (<#=code.Escape(navProperty)#> != null)
{
hasChanges = <#=code.Escape(navProperty)#>.ObjectGraphHasChanges(visitedGraph);
if (hasChanges) return true;
}
<#
}
}
#>
return false;
}
<#
}
else
{
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
internal override bool ObjectGraphHasChanges(List<object> objectList)
{
// if already visited this object, just return false
if (objectList.Any(n => ReferenceEquals(n, this))) return false;
bool hasChanges = base.ObjectGraphHasChanges(objectList);
if (hasChanges) return true;
// if not, add itself to the visited graph
var visitedGraph = objectList.ToList();
visitedGraph.Add(this);
// call ObjectGraphHasChanges() on all Navigation properties
<#
foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
{
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
foreach (var item in <#=code.Escape(navProperty)#>)
{
hasChanges = item.ObjectGraphHasChanges(visitedGraph);
if (hasChanges) return true;
}
<#
}
else
{
#>
if (<#=code.Escape(navProperty)#> != null)
{
hasChanges = <#=code.Escape(navProperty)#>.ObjectGraphHasChanges(visitedGraph);
if (hasChanges) return true;
}
<#
}
}
#>
return false;
}
<#
}
}
if (entity.BaseType == null)
{
#>
/// <summary>
/// Returns the estimate size of the entity object along with its object graph
/// </summary>
public long EstimateObjectGraphSize()
{
long size = 0;
var visitedGraph = new List<object>();
EstimateObjectGraphSize(ref size, ref visitedGraph);
return size;
}
<#
}
#>
internal <#=entity.BaseType == null ? "virtual " : "override " #>void EstimateObjectGraphSize(ref long size, ref List<object> visitedGraph)
{
// if already visited this object, just return
if (visitedGraph.Any(n => ReferenceEquals(n, this))) return;
<#
if (entity.BaseType != null)
{
#>
// call base EstimateObjectGraphSize()
base.EstimateObjectGraphSize(ref size, ref visitedGraph);
<#
}
#>
size += EstimateSize;
if (visitedGraph.All(i => !ReferenceEquals(i, this))) visitedGraph.Add(this);
<#
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
// call EstimateObjectGraphSize() on all Navigation properties
<#
}
foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
{
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
foreach (var item in <#=code.Escape(navProperty)#>)
{
item.EstimateObjectGraphSize(ref size, ref visitedGraph);
}
<#
}
else
{
#>
if (<#=code.Escape(navProperty)#> != null)
{
<#=code.Escape(navProperty)#>.EstimateObjectGraphSize(ref size, ref visitedGraph);
}
<#
}
}
#>
}
<#
if (entity.BaseType == null)
{
#>
/// <summary>
/// Returns the estimate size of the optimized entity object graph
/// with only objects that have changes
/// </summary>
public long EstimateObjectGraphChangeSize()
{
long size = 0;
if (!ObjectGraphHasChanges()) return size;
var visitedGraph = new List<object> {this};
EstimateObjectGraphChangeSize(ref size, visitedGraph);
return size;
}
<#
}
#>
internal <#=entity.BaseType == null ? "virtual " : "override " #>void EstimateObjectGraphChangeSize(ref long size, List<object> objectList)
{
<#
if (entity.BaseType != null)
{
#>
// call base EstimateObjectGraphChangeSize()
base.EstimateObjectGraphChangeSize(ref size, objectList);
<#
}
#>
size += EstimateSize;
<#
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
// call EstimateObjectGraphChangeSize() on all Navigation properties that has change
<#
}
foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
{
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
foreach (var n in <#=code.Escape(navProperty)#>)
{
// if n has already been visited, we need to skip it
if (objectList.All(i => !ReferenceEquals(i, n)))
{
if (ChangeTracker.ObjectsAddedToCollectionProperties.ContainsKey("<#=code.Escape(navProperty)#>")
&& ChangeTracker.ObjectsAddedToCollectionProperties["<#=code.Escape(navProperty)#>"].Contains(n))
{
// if n exists in ObjectsAddedToCollectionProperties, we need to add its size
var visitedGraph = objectList.ToList();
visitedGraph.Add(n);
n.EstimateObjectGraphChangeSize(ref size, visitedGraph);
}
else if (n.ObjectGraphHasChanges(objectList))
{
// if n has changes, we also need to add its size
var visitedGraph = objectList.ToList();
visitedGraph.Add(n);
n.EstimateObjectGraphChangeSize(ref size, visitedGraph);
}
}
}
<#
}
else
{
#>
// if <#=code.Escape(navProperty)#> has already been visited, we need to skip it
if (<#=code.Escape(navProperty)#> != null && objectList.All(i => !ReferenceEquals(i, <#=code.Escape(navProperty)#>)))
{
if (<#=code.Escape(navProperty)#>.ObjectGraphHasChanges(objectList))
{
var visitedGraph = objectList.ToList();
visitedGraph.Add(<#=code.Escape(navProperty)#>);
<#=code.Escape(navProperty)#>.EstimateObjectGraphChangeSize(ref size, visitedGraph);
}
}
<#
}
}
#>
}
<#
if (entity.BaseType == null)
{
#>
/// <summary>
/// Returns an optimized entity object graph with only objects that have changes
/// </summary>
public IObjectWithChangeTracker GetObjectGraphChanges()
{
if (!ObjectGraphHasChanges()) return null;
var item = this.Clone();
var visitedGraph = new List<object> { item };
// loop through all navigation properties and trim any unchanged items
item.TrimUnchangedEntities(visitedGraph);
return item;
}
internal virtual void TrimUnchangedEntities(List<object> objectList)
{
<#
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
bool changeTrackingEnabled = ChangeTracker.ChangeTrackingEnabled;
this.StopTracking();
// trim all navigation property items that do not have any change
<#
}
foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
{
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
foreach (var n in <#=code.Escape(navProperty)#>.ToList())
{
// if n has already been visited, we need to skip it
if (objectList.All(i => !ReferenceEquals(i, n)))
{
if (ChangeTracker.ObjectsAddedToCollectionProperties.ContainsKey("<#=code.Escape(navProperty)#>")
&& ChangeTracker.ObjectsAddedToCollectionProperties["<#=code.Escape(navProperty)#>"].Contains(n))
{
// if n exists in ObjectsAddedToCollectionProperties, we need to keep it
var visitedGraph = objectList.ToList();
visitedGraph.Add(n);
n.TrimUnchangedEntities(visitedGraph);
}
else if (n.ObjectGraphHasChanges(objectList))
{
// if n has changes, we also need to keep it
var visitedGraph = objectList.ToList();
visitedGraph.Add(n);
n.TrimUnchangedEntities(visitedGraph);
}
else
{
<#=code.Escape(navProperty)#>.Remove(n);
}
}
}
<#
}
else
{
#>
// if <#=code.Escape(navProperty)#> has already been visited, we need to skip it
if (<#=code.Escape(navProperty)#> != null && objectList.All(i => !ReferenceEquals(i, <#=code.Escape(navProperty)#>)))
{
if (<#=code.Escape(navProperty)#>.ObjectGraphHasChanges(objectList))
{
var visitedGraph = objectList.ToList();
visitedGraph.Add(<#=code.Escape(navProperty)#>);
<#=code.Escape(navProperty)#>.TrimUnchangedEntities(visitedGraph);
}
else
{
<#=code.Escape(navProperty)#> = null;
}
}
<#
}
}
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
ChangeTracker.ChangeTrackingEnabled = changeTrackingEnabled;
<#
}
#>
}
<#
}
else
{
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
internal override void TrimUnchangedEntities(List<object> objectList)
{
// call base TrimUnchangedEntities() first
base.TrimUnchangedEntities(objectList);
bool changeTrackingEnabled = ChangeTracker.ChangeTrackingEnabled;
this.StopTracking();
// trim all navigation property items that do not have any change
<#
foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
{
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
foreach (var n in <#=code.Escape(navProperty)#>.ToList())
{
// if n has already been visited, we need to skip it
if (objectList.All(i => !ReferenceEquals(i, n)))
{
if (ChangeTracker.ObjectsAddedToCollectionProperties.ContainsKey("<#=code.Escape(navProperty)#>")
&& ChangeTracker.ObjectsAddedToCollectionProperties["<#=code.Escape(navProperty)#>"].Contains(n))
{
// if n exists in ObjectsAddedToCollectionProperties, we need to keep it
var visitedGraph = objectList.ToList();
visitedGraph.Add(n);
n.TrimUnchangedEntities(visitedGraph);
}
else if (n.ObjectGraphHasChanges(objectList))
{
// if n has changes, we also need to keep it
var visitedGraph = objectList.ToList();
visitedGraph.Add(n);
n.TrimUnchangedEntities(visitedGraph);
}
else
{
<#=code.Escape(navProperty)#>.Remove(n);
}
}
}
<#
}
else
{
#>
// if <#=code.Escape(navProperty)#> has already been visited, we need to skip it
if (<#=code.Escape(navProperty)#> != null && objectList.All(i => !ReferenceEquals(i, <#=code.Escape(navProperty)#>)))
{
if (<#=code.Escape(navProperty)#>.ObjectGraphHasChanges(objectList))
{
var visitedGraph = objectList.ToList();
visitedGraph.Add(<#=code.Escape(navProperty)#>);
<#=code.Escape(navProperty)#>.TrimUnchangedEntities(visitedGraph);
}
else
{
<#=code.Escape(navProperty)#> = null;
}
}
<#
}
}
#>
ChangeTracker.ChangeTrackingEnabled = changeTrackingEnabled;
}
<#
}
}
region.End();
region.Begin("IClientChangeTracking Helper Property");
#>
internal <#=entity.BaseType == null ? "virtual " : "override " #>long EstimateSize
{
get
{
long _size = 0;
<#
if (entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity).Count() > 0)
{
#>
// estimate size of all Primitive Properties
<#
}
foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity))
{
switch (((PrimitiveType)edmProperty.TypeUsage.EdmType).PrimitiveTypeKind)
{
case PrimitiveTypeKind.Binary:
#>
if (<#=code.Escape(edmProperty)#> != null)
_size += <#=code.Escape(edmProperty)#>.Length * sizeof (Byte); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Boolean:
#>
_size += sizeof(Boolean); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Byte:
#>
_size += sizeof(Byte); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.DateTime:
#>
_size += sizeof(ulong); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.DateTimeOffset:
#>
_size += sizeof(ulong) + sizeof(short); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Decimal:
#>
_size += sizeof(Decimal); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Double:
#>
_size += sizeof(Double); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Guid:
#>
_size += sizeof(int) + sizeof(short) * 2 + sizeof(byte) * 8; // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Int16:
#>
_size += sizeof(Int16); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Int32:
#>
_size += sizeof(Int32); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Int64:
#>
_size += sizeof(Int64); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.SByte:
#>
_size += sizeof(SByte); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Single:
#>
_size += sizeof(Single); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.String:
#>
if (<#=code.Escape(edmProperty)#> != null)
_size += <#=code.Escape(edmProperty)#>.Length * sizeof(char); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Time:
#>
_size += sizeof(long); // <#=code.Escape(edmProperty)#>
<#
break;
}
}
if (entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity).Count() > 0)
{
#>
// get EstimateSize of all Complex Properties
<#
}
foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity))
{
#>
if (<#=code.Escape(edmProperty)#> != null)
_size += <#=code.Escape(edmProperty)#>.EstimateSize; // <#=code.Escape(edmProperty)#>
<#
}
#>
return _size;
}
}
<#
region.End();
region.Begin("IChangeTracking and IRevertibleChangeTracking interfaces");
WriteIRevertibleChangeTrackingInterface();
region.End();
region.Begin("IDataErrorInfo interface");
WriteIDataErrorInfoInterfaceForEntityType(entity);
region.End();
region.Begin("IDataErrorInfo Protected & Private Helper Methods");
if (entity.BaseType == null)
{
#>
/// <summary>
/// Declares a new error for the property name provided, or the entity if
/// propertyName is String.Empty/null.
/// </summary>
protected void AddError(string propertyName, ValidationResult validationResult)
{
if (validationResult == null)
{
throw new ArgumentNullException("validationResult");
}
if (propertyName == null)
{
propertyName = string.Empty;
}
if (!ValidationErrors.ContainsKey(propertyName))
{
ValidationErrors.Add(propertyName, validationResult);
OnPropertyChanged(propertyName);
}
}
/// <summary>
/// Removes one specific error for the provided property name.
/// </summary>
/// <param name="propertyName"></param>
/// <param name="validationResult"></param>
protected void RemoveError(string propertyName, ValidationResult validationResult)
{
if (validationResult == null)
{
throw new ArgumentNullException("validationResult");
}
if (propertyName == null)
{
propertyName = string.Empty;
}
if (ValidationErrors.ContainsKey(propertyName))
{
if (string.Equals(ValidationErrors[propertyName].ErrorMessage, validationResult.ErrorMessage, StringComparison.CurrentCulture))
{
// This entity no longer exposes error for this property name.
ValidationErrors.Remove(propertyName);
OnPropertyChanged(propertyName);
}
}
}
/// <summary>
/// Removes the known error from the cache, for the provided property name.
/// </summary>
/// <param name="propertyName">Propery name or String.Empty/null for top-level errors</param>
protected void ClearErrors(string propertyName)
{
if (propertyName == null)
{
propertyName = string.Empty;
}
if (ValidationErrors.ContainsKey(propertyName))
{
// This entity no longer exposes error for this property name.
ValidationErrors.Remove(propertyName);
OnPropertyChanged(propertyName);
}
}
/// <summary>
/// Removes the known errors for all property names.
/// </summary>
protected void ClearErrors()
{
foreach (string propertyName in ValidationErrors.Keys.ToList())
{
// This entity no longer exposes error for this property name.
ValidationErrors.Remove(propertyName);
OnPropertyChanged(propertyName);
}
}
/// <summary>
/// Gets a value indicating whether or not top-level validation rules
/// must be applied whenever any entity property changes.
/// </summary>
protected static Boolean ValidateEntityOnPropertyChanged;
<#
}
#>
/// <summary>
/// Removes any known errors for the provided property name
/// by calling ClearErrors()
/// </summary>
/// <param name="propertyName">Propery name or String.Empty/null for top-level errors</param>
partial void PropertySetterEntry(string propertyName)
{
if (IsDeserializing)
{
return;
}
if (ValidateEntityOnPropertyChanged)
{
ClearErrors();
}
else
{
ClearErrors(propertyName);
}
}
/// <summary>
/// Validates for any known errors for the provided property name
/// </summary>
/// <param name="propertyName">Propery name or String.Empty/null for top-level errors</param>
/// <param name="propertyValue">Property value</param>
partial void PropertySetterExit(string propertyName, object propertyValue)
{
if (IsDeserializing)
{
return;
}
if (ValidateEntityOnPropertyChanged)
{
Validate(string.Empty, this);
}
else
{
Validate(propertyName, propertyValue);
}
}
<#
foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity))
{
#>
// Synchronize validation error changes from Complex Type property
private void Handle<#=edmProperty.Name#>ValidationResultChanged(object sender, ValidationResultChangedEventArgs e)
{
string propertyName;
if (string.IsNullOrEmpty(e.PropertyName))
propertyName = "<#=edmProperty.Name#>";
else
propertyName = "<#=edmProperty.Name#>." + e.PropertyName;
foreach (ValidationResult item in e.AddedItems)
{
AddError(propertyName, item);
}
foreach (ValidationResult item in e.RemovedItems)
{
RemoveError(propertyName, item);
}
}
<#
}
region.End();
region.Begin("IEditableObject interface");
if (codeForIEditableObject == "true")
{
#>
private Dictionary<string , object> _cache;
public <#=entity.BaseType == null ? "virtual " : "override " #>void BeginEdit()
{
<#
if (entity.BaseType != null)
{
#>
// call base BeginEdit() first
base.BeginEdit();
<#
}
#>
if (_cache == null) _cache = new Dictionary<string, object>();
<#
if (entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity).Count() > 0)
{
#>
// copy all Primitive Properties except the primary key fields
<#
}
foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity))
{
if (!ef.IsKey(edmProperty))
{
#>
_cache["<#=code.Escape(edmProperty)#>"] = <#=code.Escape(edmProperty)#>;
<#
}
}
if (entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity).Count() > 0)
{
#>
// call BeginEdit() on all Complex Properties
<#
}
foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity))
{
#>
((IEditableObject)<#=code.Escape(edmProperty)#>).BeginEdit();
<#
}
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
// copy all Navigation Properties
<#
}
foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
{
#>
_cache["<#=code.Escape(navProperty)#>"] = <#=code.Escape(navProperty)#>;
<#
}
if (entity.BaseType == null)
{
#>
// copy ChangeTracker
_cache["ChangeTracker"] = ChangeTracker.Clone();
<#
}
#>
}
public <#=entity.BaseType == null ? "virtual " : "override " #>void CancelEdit()
{
<#
if (entity.BaseType != null)
{
#>
// call base CancelEdit() first
base.CancelEdit();
<#
}
#>
if (_cache == null) _cache = new Dictionary<string, object>();
if (_cache.Count == 0) return;
bool changeTrackingEnabled = ChangeTracker.ChangeTrackingEnabled;
this.StopTracking();
<#
if (entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity).Count() > 0)
{
#>
// copy all Primitive Properties except the primary key fields
<#
}
foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == entity))
{
if (!ef.IsKey(edmProperty))
{
if (((PrimitiveType)edmProperty.TypeUsage.EdmType).PrimitiveTypeKind == PrimitiveTypeKind.Binary &&
entity.NavigationProperties.Where(np=>np.GetDependentProperties().Contains(edmProperty)).Any())
{
#>
if (!EqualityComparer.BinaryEquals(<#=code.Escape(edmProperty)#>, (<#=code.Escape(edmProperty.TypeUsage)#>)_cache["<#=code.Escape(edmProperty)#>"]))
<#
}
else
{
#>
if (<#=code.Escape(edmProperty)#> != (<#=code.Escape(edmProperty.TypeUsage)#>)_cache["<#=code.Escape(edmProperty)#>"])
<#
}
#>
<#=code.Escape(edmProperty)#> = (<#=code.Escape(edmProperty.TypeUsage)#>)_cache["<#=code.Escape(edmProperty)#>"];
else
OnPropertyChanged("<#=edmProperty.Name#>");
<#
}
}
if (entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity).Count() > 0)
{
#>
// call CancelEdit() on all Complex Properties
<#
}
foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity))
{
#>
((IEditableObject)<#=code.Escape(edmProperty)#>).CancelEdit();
<#
}
if (entity.NavigationProperties.Where(np => np.DeclaringType == entity).Count() > 0)
{
#>
// copy all Navigation Properties
<#
}
foreach (NavigationProperty navProperty in entity.NavigationProperties.Where(np => np.DeclaringType == entity))
{
if (navProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
<#=code.Escape(navProperty)#> = (TrackableCollection<<#=code.Escape(navProperty.ToEndMember.GetEntityType())#>>)_cache["<#=code.Escape(navProperty)#>"];
<#
}
else
{
#>
<#=code.Escape(navProperty)#> = (<#=code.Escape(navProperty.ToEndMember.GetEntityType())#>)_cache["<#=code.Escape(navProperty)#>"];
<#
}
}
if (entity.BaseType == null)
{
#>
// copy ChangeTracker
ChangeTracker = (ObjectChangeTracker)_cache["ChangeTracker"];
<#
}
#>
ChangeTracker.ChangeTrackingEnabled = changeTrackingEnabled;
_cache.Clear();
}
public <#=entity.BaseType == null ? "virtual " : "override " #>void EndEdit()
{
<#
if (entity.BaseType != null)
{
#>
// call base EndEdit() first
base.EndEdit();
<#
}
#>
if (_cache == null) _cache = new Dictionary<string, object>();
_cache.Clear();
<#
if (entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity).Count() > 0)
{
#>
// call EndEdit() on all Complex Properties
<#
}
foreach (EdmProperty edmProperty in entity.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == entity))
{
#>
((IEditableObject)<#=code.Escape(edmProperty)#>).EndEdit();
<#
}
#>
}
<#
}
region.End();
#>
}
<#
EndNamespace(namespaceName);
#>
#endif
<#
}
}
// Emit Complex Types
foreach (ComplexType complex in ItemCollection.GetItems<ComplexType>().OrderBy(e => e.Name))
{
if (codeForSilverlight == @"Silverlight4")
{
fileManager.StartNewFile("SL4." + complex.Name + ".cs");
#>
#if SILVERLIGHT
<#
BeginNamespace(namespaceName, code);
#>
<#=Accessibility.ForType(complex)#> partial class <#=code.Escape(complex)#><#=code.StringBefore(" : ", code.Escape(complex.BaseType))#><#=complex.BaseType == null ? " : " : ", "#>INotifyDataErrorInfo, INotifyValidationResultChanged<#=codeForIEditableObject == "true" ? ", IEditableObject" : "" #>
{
<#
region.Begin("INotifyDataErrorInfo interface");
WriteINotifyDataErrorInfoInterfaceForComplexType();
region.End();
region.Begin("INotifyDataErrorInfo Protected & Private Helper Methods");
#>
/// <summary>
/// Declares a new error for the property name provided, or the object if
/// propertyName is String.Empty/null.
/// </summary>
protected void AddError(string propertyName, ValidationResult validationResult)
{
if (validationResult == null)
{
throw new ArgumentNullException("validationResult");
}
if (propertyName == null)
{
propertyName = string.Empty;
}
List<ValidationResult> errors;
if (!ValidationErrors.ContainsKey(propertyName))
{
errors = new List<ValidationResult>();
ValidationErrors.Add(propertyName, errors);
}
else
{
errors = ValidationErrors[propertyName];
}
// search for duplicate error message with the same propertyName
var foundError = errors.Where(n =>
n.ErrorMessage == validationResult.ErrorMessage).FirstOrDefault();
if (foundError == null)
{
errors.Insert(0, validationResult);
RaiseErrorsChanged(propertyName);
List<ValidationResult> addedItems = new List<ValidationResult> {validationResult};
OnValidationResultChanged(propertyName, null, addedItems);
}
}
/// <summary>
/// Removes one specific error for the provided property name.
/// </summary>
/// <param name="propertyName"></param>
/// <param name="validationResult"></param>
protected void RemoveError(string propertyName, ValidationResult validationResult)
{
if (validationResult == null)
{
throw new ArgumentNullException("validationResult");
}
if (propertyName == null)
{
propertyName = string.Empty;
}
List<ValidationResult> errors;
if (ValidationErrors.ContainsKey(propertyName))
{
errors = ValidationErrors[propertyName];
// search for the error message that need to be removed
var foundError = errors.Where(n =>
n.ErrorMessage == validationResult.ErrorMessage).FirstOrDefault();
if (foundError != null)
{
errors.Remove(foundError);
if (errors.Count == 0)
{
// This entity no longer exposes errors for this property name.
ValidationErrors.Remove(propertyName);
}
RaiseErrorsChanged(propertyName);
}
}
}
/// <summary>
/// Removes the known errors from the cache, for the provided property name.
/// </summary>
/// <param name="propertyName">Propery name or String.Empty/null for top-level errors</param>
protected void ClearErrors(string propertyName)
{
if (propertyName == null)
{
propertyName = string.Empty;
}
if (ValidationErrors.ContainsKey(propertyName))
{
List<ValidationResult> removedItems = new List<ValidationResult>(ValidationErrors[propertyName]);
// This object no longer exposes errors for this property name.
ValidationErrors.Remove(propertyName);
RaiseErrorsChanged(propertyName);
OnValidationResultChanged(propertyName, removedItems, null);
}
}
/// <summary>
/// Removes the known errors for all property names.
/// </summary>
protected void ClearErrors()
{
List<ValidationResult> removedItems;
foreach (string propertyName in ValidationErrors.Keys.ToList())
{
removedItems = new List<ValidationResult>(ValidationErrors[propertyName]);
// This object no longer exposes errors for this property name.
ValidationErrors.Remove(propertyName);
RaiseErrorsChanged(propertyName);
OnValidationResultChanged(propertyName, removedItems, null);
}
}
/// <summary>
/// Gets a value indicating whether or not top-level validation rules
/// must be applied whenever any property changes.
/// </summary>
protected static Boolean ValidateEntityOnPropertyChanged;
/// <summary>
/// Removes any known errors for the provided property name
/// by calling ClearErrors()
/// </summary>
/// <param name="propertyName">Propery name or String.Empty/null for top-level errors</param>
partial void PropertySetterEntry(string propertyName)
{
if (IsDeserializing)
{
return;
}
if (ValidateEntityOnPropertyChanged)
{
ClearErrors();
}
else
{
ClearErrors(propertyName);
}
}
/// <summary>
/// Validates for any known errors for the provided property name
/// </summary>
/// <param name="propertyName">Propery name or String.Empty/null for top-level errors</param>
/// <param name="propertyValue">Property value</param>
partial void PropertySetterExit(string propertyName, object propertyValue)
{
if (IsDeserializing)
{
return;
}
if (ValidateEntityOnPropertyChanged)
{
Validate(string.Empty, this);
}
else
{
Validate(propertyName, propertyValue);
}
}
<#
foreach (EdmProperty edmProperty in complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex))
{
#>
// Synchronize validation error changes from Complex Type property
private void Handle<#=edmProperty.Name#>ValidationResultChanged(object sender, ValidationResultChangedEventArgs e)
{
string propertyName;
if (string.IsNullOrEmpty(e.PropertyName))
propertyName = "<#=edmProperty.Name#>";
else
propertyName = "<#=edmProperty.Name#>." + e.PropertyName;
foreach (ValidationResult item in e.AddedItems)
{
AddError(propertyName, item);
}
foreach (ValidationResult item in e.RemovedItems)
{
RemoveError(propertyName, item);
}
}
<#
}
region.End();
region.Begin("INotifyValidationResultChanged interface");
WriteINotifyValidationResultChangedInterface();
region.End();
region.Begin("IClientChangeTracking Helper Property");
#>
internal long EstimateSize
{
get
{
long _size = 0;
<#
if (complex.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == complex).Count() > 0)
{
#>
// estimate size of all Primitive Properties
<#
}
foreach (EdmProperty edmProperty in complex.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == complex))
{
switch (((PrimitiveType)edmProperty.TypeUsage.EdmType).PrimitiveTypeKind)
{
case PrimitiveTypeKind.Binary:
#>
if (<#=code.Escape(edmProperty)#> != null)
_size += <#=code.Escape(edmProperty)#>.Length * sizeof (Byte); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Boolean:
#>
_size += sizeof(Boolean); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Byte:
#>
_size += sizeof(Byte); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.DateTime:
#>
_size += sizeof(ulong); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.DateTimeOffset:
#>
_size += sizeof(ulong) + sizeof(short); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Decimal:
#>
_size += sizeof(Decimal); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Double:
#>
_size += sizeof(Double); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Guid:
#>
_size += sizeof(int) + sizeof(short) * 2 + sizeof(byte) * 8; // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Int16:
#>
_size += sizeof(Int16); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Int32:
#>
_size += sizeof(Int32); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Int64:
#>
_size += sizeof(Int64); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.SByte:
#>
_size += sizeof(SByte); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Single:
#>
_size += sizeof(Single); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.String:
#>
if (<#=code.Escape(edmProperty)#> != null)
_size += <#=code.Escape(edmProperty)#>.Length * sizeof(char); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Time:
#>
_size += sizeof(long); // <#=code.Escape(edmProperty)#>
<#
break;
}
}
if (complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex).Count() > 0)
{
#>
// get EstimateSize of all Complex Properties
<#
}
foreach (EdmProperty edmProperty in complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex))
{
#>
if (<#=code.Escape(edmProperty)#> != null)
_size += <#=code.Escape(edmProperty)#>.EstimateSize; // <#=code.Escape(edmProperty)#>
<#
}
#>
return _size;
}
}
<#
region.End();
region.Begin("IEditableObject interface");
if (codeForIEditableObject == "true")
{
#>
private <#=code.Escape(complex)#> _cache;
void IEditableObject.BeginEdit()
{
_cache = new <#=code.Escape(complex)#>
{
<#
if (complex.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == complex).Count() > 0)
{
#>
// copy all Primitive Properties
<#
}
foreach (EdmProperty edmProperty in complex.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == complex))
{
#>
<#=code.FieldName(edmProperty)#> = <#=code.Escape(edmProperty)#>,
<#
}
#>
};
<#
if (complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex).Count() > 0)
{
#>
// call BeginEdit() on all Complex Properties
<#
}
foreach (EdmProperty edmProperty in complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex))
{
#>
((IEditableObject)<#=code.Escape(edmProperty)#>).BeginEdit();
<#
}
#>
}
void IEditableObject.CancelEdit()
{
if (_cache == null) return;
<#
if (complex.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == complex).Count() > 0)
{
#>
// copy all Primitive Properties
<#
}
foreach (EdmProperty edmProperty in complex.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == complex))
{
#>
if (<#=code.Escape(edmProperty)#> != _cache.<#=code.FieldName(edmProperty)#>)
<#=code.Escape(edmProperty)#> = _cache.<#=code.FieldName(edmProperty)#>;
else
OnPropertyChanged("<#=edmProperty.Name#>");
<#
}
if (complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex).Count() > 0)
{
#>
// call CancelEdit() on all Complex Properties
<#
}
foreach (EdmProperty edmProperty in complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex))
{
#>
((IEditableObject)<#=code.Escape(edmProperty)#>).CancelEdit();
<#
}
#>
_cache = null;
}
void IEditableObject.EndEdit()
{
_cache = null;
<#
if (complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex).Count() > 0)
{
#>
// call EndEdit() on all Complex Properties
<#
}
foreach (EdmProperty edmProperty in complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex))
{
#>
((IEditableObject)<#=code.Escape(edmProperty)#>).EndEdit();
<#
}
#>
}
<#
}
region.End();
#>
}
<#
EndNamespace(namespaceName);
#>
#endif
<#
}
if (codeForWPF == @"WPF4")
{
fileManager.StartNewFile("WPF4." + complex.Name + ".cs");
#>
#if WPF
<#
BeginNamespace(namespaceName, code);
#>
<#=Accessibility.ForType(complex)#> partial class <#=code.Escape(complex)#><#=code.StringBefore(" : ", code.Escape(complex.BaseType))#><#=complex.BaseType == null ? " : " : ", "#>IDataErrorInfo, INotifyValidationResultChanged<#=codeForIEditableObject == "true" ? ", IEditableObject" : "" #>
{
<#
region.Begin("IDataErrorInfo interface");
WriteIDataErrorInfoInterfaceForComplexType();
region.End();
region.Begin("IDataErrorInfo Protected & Private Helper Methods");
#>
/// <summary>
/// Declares a new error for the property name provided, or the object if
/// propertyName is String.Empty/null.
/// </summary>
protected void AddError(string propertyName, ValidationResult validationResult)
{
if (validationResult == null)
{
throw new ArgumentNullException("validationResult");
}
if (propertyName == null)
{
propertyName = string.Empty;
}
if (!ValidationErrors.ContainsKey(propertyName))
{
ValidationErrors.Add(propertyName, validationResult);
OnPropertyChanged(propertyName);
List<ValidationResult> addedItems = new List<ValidationResult> {validationResult};
OnValidationResultChanged(propertyName, null, addedItems);
}
}
/// <summary>
/// Removes one specific error for the provided property name.
/// </summary>
/// <param name="propertyName"></param>
/// <param name="validationResult"></param>
protected void RemoveError(string propertyName, ValidationResult validationResult)
{
if (validationResult == null)
{
throw new ArgumentNullException("validationResult");
}
if (propertyName == null)
{
propertyName = string.Empty;
}
if (ValidationErrors.ContainsKey(propertyName))
{
if (string.Equals(ValidationErrors[propertyName].ErrorMessage, validationResult.ErrorMessage, StringComparison.CurrentCulture))
{
// This entity no longer exposes error for this property name.
ValidationErrors.Remove(propertyName);
OnPropertyChanged(propertyName);
}
}
}
/// <summary>
/// Removes the known error from the cache, for the provided property name.
/// </summary>
/// <param name="propertyName">Propery name or String.Empty/null for top-level errors</param>
protected void ClearErrors(string propertyName)
{
if (propertyName == null)
{
propertyName = string.Empty;
}
if (ValidationErrors.ContainsKey(propertyName))
{
List<ValidationResult> removedItems = new List<ValidationResult> {ValidationErrors[propertyName]};
// This entity no longer exposes error for this property name.
ValidationErrors.Remove(propertyName);
OnPropertyChanged(propertyName);
OnValidationResultChanged(propertyName, removedItems, null);
}
}
/// <summary>
/// Removes the known errors for all property names.
/// </summary>
protected void ClearErrors()
{
foreach (string propertyName in ValidationErrors.Keys.ToList())
{
List<ValidationResult> removedItems = new List<ValidationResult> { ValidationErrors[propertyName] };
// This entity no longer exposes error for this property name.
ValidationErrors.Remove(propertyName);
OnPropertyChanged(propertyName);
OnValidationResultChanged(propertyName, removedItems, null);
}
}
/// <summary>
/// Gets a value indicating whether or not top-level validation rules
/// must be applied whenever any property changes.
/// </summary>
protected static Boolean ValidateEntityOnPropertyChanged;
/// <summary>
/// Removes any known errors for the provided property name
/// by calling ClearErrors()
/// </summary>
/// <param name="propertyName">Propery name or String.Empty/null for top-level errors</param>
partial void PropertySetterEntry(string propertyName)
{
if (IsDeserializing)
{
return;
}
if (ValidateEntityOnPropertyChanged)
{
ClearErrors();
}
else
{
ClearErrors(propertyName);
}
}
/// <summary>
/// Validates for any known errors for the provided property name
/// </summary>
/// <param name="propertyName">Propery name or String.Empty/null for top-level errors</param>
/// <param name="propertyValue">Property value</param>
partial void PropertySetterExit(string propertyName, object propertyValue)
{
if (IsDeserializing)
{
return;
}
if (ValidateEntityOnPropertyChanged)
{
Validate(string.Empty, this);
}
else
{
Validate(propertyName, propertyValue);
}
}
<#
foreach (EdmProperty edmProperty in complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex))
{
#>
// Synchronize validation error changes from Complex Type property
private void Handle<#=edmProperty.Name#>ValidationResultChanged(object sender, ValidationResultChangedEventArgs e)
{
string propertyName;
if (string.IsNullOrEmpty(e.PropertyName))
propertyName = "<#=edmProperty.Name#>";
else
propertyName = "<#=edmProperty.Name#>." + e.PropertyName;
foreach (ValidationResult item in e.AddedItems)
{
AddError(propertyName, item);
}
foreach (ValidationResult item in e.RemovedItems)
{
RemoveError(propertyName, item);
}
}
<#
}
region.End();
region.Begin("INotifyValidationResultChanged interface");
WriteINotifyValidationResultChangedInterface();
region.End();
region.Begin("IClientChangeTracking Helper Property");
#>
internal long EstimateSize
{
get
{
long _size = 0;
<#
if (complex.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == complex).Count() > 0)
{
#>
// estimate size of all Primitive Properties
<#
}
foreach (EdmProperty edmProperty in complex.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == complex))
{
switch (((PrimitiveType)edmProperty.TypeUsage.EdmType).PrimitiveTypeKind)
{
case PrimitiveTypeKind.Binary:
#>
if (<#=code.Escape(edmProperty)#> != null)
_size += <#=code.Escape(edmProperty)#>.Length * sizeof (Byte); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Boolean:
#>
_size += sizeof(Boolean); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Byte:
#>
_size += sizeof(Byte); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.DateTime:
#>
_size += sizeof(ulong); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.DateTimeOffset:
#>
_size += sizeof(ulong) + sizeof(short); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Decimal:
#>
_size += sizeof(Decimal); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Double:
#>
_size += sizeof(Double); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Guid:
#>
_size += sizeof(int) + sizeof(short) * 2 + sizeof(byte) * 8; // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Int16:
#>
_size += sizeof(Int16); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Int32:
#>
_size += sizeof(Int32); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Int64:
#>
_size += sizeof(Int64); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.SByte:
#>
_size += sizeof(SByte); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Single:
#>
_size += sizeof(Single); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.String:
#>
if (<#=code.Escape(edmProperty)#> != null)
_size += <#=code.Escape(edmProperty)#>.Length * sizeof(char); // <#=code.Escape(edmProperty)#>
<#
break;
case PrimitiveTypeKind.Time:
#>
_size += sizeof(long); // <#=code.Escape(edmProperty)#>
<#
break;
}
}
if (complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex).Count() > 0)
{
#>
// get EstimateSize of all Complex Properties
<#
}
foreach (EdmProperty edmProperty in complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex))
{
#>
if (<#=code.Escape(edmProperty)#> != null)
_size += <#=code.Escape(edmProperty)#>.EstimateSize; // <#=code.Escape(edmProperty)#>
<#
}
#>
return _size;
}
}
<#
region.End();
region.Begin("IEditableObject interface");
if (codeForIEditableObject == "true")
{
#>
private <#=code.Escape(complex)#> _cache;
void IEditableObject.BeginEdit()
{
_cache = new <#=code.Escape(complex)#>
{
<#
if (complex.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == complex).Count() > 0)
{
#>
// copy all Primitive Properties
<#
}
foreach (EdmProperty edmProperty in complex.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == complex))
{
#>
<#=code.FieldName(edmProperty)#> = <#=code.Escape(edmProperty)#>,
<#
}
#>
};
<#
if (complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex).Count() > 0)
{
#>
// call BeginEdit() on all Complex Properties
<#
}
foreach (EdmProperty edmProperty in complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex))
{
#>
((IEditableObject)<#=code.Escape(edmProperty)#>).BeginEdit();
<#
}
#>
}
void IEditableObject.CancelEdit()
{
if (_cache == null) return;
<#
if (complex.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == complex).Count() > 0)
{
#>
// copy all Primitive Properties
<#
}
foreach (EdmProperty edmProperty in complex.Properties.Where(p => p.TypeUsage.EdmType is PrimitiveType && p.DeclaringType == complex))
{
#>
if (<#=code.Escape(edmProperty)#> != _cache.<#=code.FieldName(edmProperty)#>)
<#=code.Escape(edmProperty)#> = _cache.<#=code.FieldName(edmProperty)#>;
else
OnPropertyChanged("<#=edmProperty.Name#>");
<#
}
if (complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex).Count() > 0)
{
#>
// call CancelEdit() on all Complex Properties
<#
}
foreach (EdmProperty edmProperty in complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex))
{
#>
((IEditableObject)<#=code.Escape(edmProperty)#>).CancelEdit();
<#
}
#>
_cache = null;
}
void IEditableObject.EndEdit()
{
_cache = null;
<#
if (complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex).Count() > 0)
{
#>
// call EndEdit() on all Complex Properties
<#
}
foreach (EdmProperty edmProperty in complex.Properties.Where(p => p.TypeUsage.EdmType is ComplexType && p.DeclaringType == complex))
{
#>
((IEditableObject)<#=code.Escape(edmProperty)#>).EndEdit();
<#
}
#>
}
<#
}
region.End();
#>
}
<#
EndNamespace(namespaceName);
#>
#endif
<#
}
}
if (!VerifyTypesAreCaseInsensitiveUnique(ItemCollection))
{
return "";
}
fileManager.Process();
#>
<#+
void WriteHeader(EntityFrameworkTemplateFileManager fileManager, params string[] extraUsings)
{
fileManager.StartHeader();
#>
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
<#=String.Join(String.Empty, extraUsings.Select(u => "using " + u + ";" + Environment.NewLine).ToArray())#>
<#+
fileManager.EndBlock();
}
void BeginNamespace(string namespaceName, CodeGenerationTools code)
{
CodeRegion region = new CodeRegion(this);
if (!String.IsNullOrEmpty(namespaceName))
{
#>
namespace <#=code.EscapeNamespace(namespaceName)#>
{
<#+
PushIndent(CodeRegion.GetIndent(1));
}
}
void EndNamespace(string namespaceName)
{
if (!String.IsNullOrEmpty(namespaceName))
{
PopIndent();
#>
}
<#+
}
}
void WriteNotifyValidationResultChanged()
{
#>
public class ValidationResultChangedEventArgs : EventArgs
{
public ValidationResultChangedEventArgs(string propertyName, IList<ValidationResult> removedItems, IList<ValidationResult> addedItems)
{
PropertyName = propertyName;
RemovedItems = removedItems ?? new List<ValidationResult>();
AddedItems = addedItems ?? new List<ValidationResult>();
}
public string PropertyName { get; private set; }
public IList<ValidationResult> AddedItems { get; private set; }
public IList<ValidationResult> RemovedItems { get; private set; }
}
// An interface that provides an event that fires when validation results changed.
public interface INotifyValidationResultChanged
{
event EventHandler<ValidationResultChangedEventArgs> ValidationResultChanged;
}
<#+
}
void WriteClientChangeTracking()
{
#>
// An interface that provides methods and properties for client side change tracking
public interface IClientChangeTracking
{
// accepts changes for the entity object
void AcceptChanges();
// rejects changes made to the entity object
void RejectChanges();
// whether the entity object has any changes
bool HasChanges { get; }
// accepts changes for the entity object and all objects of its object graph
void AcceptObjectGraphChanges();
// rejects changes made to the entity object and all objects of its object graph
void RejectObjectGraphChanges();
// returns whether the entity object along with its object graph has any changes
bool ObjectGraphHasChanges();
// returns the estimate size of the entity object along with its object graph
long EstimateObjectGraphSize();
// returns the estimate size of the optimized entity object graph with only objects that have changes
long EstimateObjectGraphChangeSize();
// returns an optimized entity object graph with only objects that have changes
IObjectWithChangeTracker GetObjectGraphChanges();
}
<#+
}
void WriteINotifyDataErrorInfoInterfaceForEntityType(EntityType entity)
{
if (entity.BaseType == null)
{
#>
private Dictionary<string, List<ValidationResult>> _validationErrors;
protected Dictionary<string, List<ValidationResult>> ValidationErrors
{
get { return _validationErrors ?? (_validationErrors = new Dictionary<string, List<ValidationResult>>()); }
}
protected event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
/// <summary>
/// Raises the INotifyDataErrorInfo.ErrorsChanged event
/// </summary>
protected void RaiseErrorsChanged(string propertyName)
{
if (ErrorsChanged != null)
{
ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
}
}
<#+
}
#>
event EventHandler<DataErrorsChangedEventArgs> INotifyDataErrorInfo.ErrorsChanged
{
add
{
ErrorsChanged += value;
}
remove
{
ErrorsChanged -= value;
}
}
/// <summary>
/// Gets the currently known errors for the provided property name. Use String.Empty/null
/// to retrieve entity-level errors.
/// </summary>
IEnumerable INotifyDataErrorInfo.GetErrors(string propertyName)
{
if (propertyName == null)
{
propertyName = string.Empty;
}
if (ValidationErrors.ContainsKey(propertyName))
{
return ValidationErrors[propertyName];
}
return null;
}
/// <summary>
/// Gets a value indicating whether there are known errors or not.
/// </summary>
bool INotifyDataErrorInfo.HasErrors
{
get
{
return ValidationErrors.Keys.Count != 0;
}
}
<#+
}
void WriteINotifyDataErrorInfoInterfaceForComplexType()
{
#>
private Dictionary<string, List<ValidationResult>> _validationErrors;
protected Dictionary<string, List<ValidationResult>> ValidationErrors
{
get { return _validationErrors ?? (_validationErrors = new Dictionary<string, List<ValidationResult>>()); }
}
protected event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
/// <summary>
/// Raises the INotifyDataErrorInfo.ErrorsChanged event
/// </summary>
protected void RaiseErrorsChanged(string propertyName)
{
if (ErrorsChanged != null)
{
ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
}
}
event EventHandler<DataErrorsChangedEventArgs> INotifyDataErrorInfo.ErrorsChanged
{
add
{
ErrorsChanged += value;
}
remove
{
ErrorsChanged -= value;
}
}
/// <summary>
/// Gets the currently known errors for the provided property name. Use String.Empty/null
/// to retrieve entity-level errors.
/// </summary>
IEnumerable INotifyDataErrorInfo.GetErrors(string propertyName)
{
if (propertyName == null)
{
propertyName = string.Empty;
}
if (ValidationErrors.ContainsKey(propertyName))
{
return ValidationErrors[propertyName];
}
return null;
}
/// <summary>
/// Gets a value indicating whether there are known errors or not.
/// </summary>
bool INotifyDataErrorInfo.HasErrors
{
get
{
return ValidationErrors.Keys.Count != 0;
}
}
<#+
}
void WriteIDataErrorInfoInterfaceForEntityType(EntityType entity)
{
if (entity.BaseType == null)
{
#>
private Dictionary<string, ValidationResult> _validationErrors;
protected Dictionary<string, ValidationResult> ValidationErrors
{
get
{
if (_validationErrors == null)
{
_validationErrors = new Dictionary<string, ValidationResult>();
}
return _validationErrors;
}
}
<#+
}
#>
string IDataErrorInfo.Error
{
get
{
if (ValidationErrors.ContainsKey(string.Empty))
{
return ValidationErrors[string.Empty].ErrorMessage;
}
return null;
}
}
string IDataErrorInfo.this[string propertyName]
{
get
{
if (propertyName == null)
{
propertyName = string.Empty;
}
if (ValidationErrors.ContainsKey(propertyName))
{
return ValidationErrors[propertyName].ErrorMessage;
}
return null;
}
}
<#+
}
void WriteIDataErrorInfoInterfaceForComplexType()
{
#>
private Dictionary<string, ValidationResult> _validationErrors;
protected Dictionary<string, ValidationResult> ValidationErrors
{
get
{
if (_validationErrors == null)
{
_validationErrors = new Dictionary<string, ValidationResult>();
}
return _validationErrors;
}
}
string IDataErrorInfo.Error
{
get
{
if (ValidationErrors.ContainsKey(string.Empty))
{
return ValidationErrors[string.Empty].ErrorMessage;
}
return null;
}
}
string IDataErrorInfo.this[string propertyName]
{
get
{
if (propertyName == null)
{
propertyName = string.Empty;
}
if (ValidationErrors.ContainsKey(propertyName))
{
return ValidationErrors[propertyName].ErrorMessage;
}
return null;
}
}
<#+
}
void WriteIRevertibleChangeTrackingInterface()
{
#>
void IChangeTracking.AcceptChanges()
{
this.AcceptChanges();
}
bool IChangeTracking.IsChanged
{
get { return HasChanges; }
}
void IRevertibleChangeTracking.RejectChanges()
{
this.RejectChanges();
}
<#+
}
void WriteAcceptChangesAndRejectChanges()
{
#>
/// <summary>
/// Accepts changes for the entity object
/// </summary>
void IClientChangeTracking.AcceptChanges()
{
this.AcceptChanges();
}
/// <summary>
/// Rejects changes made to the entity object
/// </summary>
void IClientChangeTracking.RejectChanges()
{
this.RejectChanges();
}
<#+
}
void WriteHasChangesProperty()
{
#>
/// <summary>
/// Returns whether the entity object has any changes
/// </summary>
public Boolean HasChanges
{
get { return _hasChanges; }
private set
{
if (_hasChanges != value)
{
_hasChanges = value;
if (_propertyChanged != null)
{
_propertyChanged(this, new PropertyChangedEventArgs("HasChanges"));
}
}
}
}
private Boolean _hasChanges = true;
<#+
}
void WriteINotifyValidationResultChangedInterface()
{
#>
private void OnValidationResultChanged(string propertyName, IList<ValidationResult> removedItems, IList<ValidationResult> addedItems)
{
if (_validationResultChanged != null)
{
_validationResultChanged(this, new ValidationResultChangedEventArgs(propertyName, removedItems, addedItems));
}
}
event EventHandler<ValidationResultChangedEventArgs> INotifyValidationResultChanged.ValidationResultChanged
{
add { _validationResultChanged += value; }
remove { _validationResultChanged -= value; }
}
private event EventHandler<ValidationResultChangedEventArgs> _validationResultChanged;
<#+
}
bool VerifyTypesAreCaseInsensitiveUnique(EdmItemCollection itemCollection)
{
Dictionary<string, bool> alreadySeen = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
foreach (StructuralType type in itemCollection.GetItems<StructuralType>())
{
if (!(type is EntityType || type is ComplexType))
{
continue;
}
if (alreadySeen.ContainsKey(type.FullName))
{
Error(String.Format(CultureInfo.CurrentCulture, "This template does not support types that differ only by case, the types {0} are not supported", type.FullName));
return false;
}
else
{
alreadySeen.Add(type.FullName, true);
}
}
return true;
}
#>