536cd135cc
Former-commit-id: 5624ac747d633e885131e8349322922b6a59baaa
223 lines
6.8 KiB
C#
223 lines
6.8 KiB
C#
//---------------------------------------------------------------------
|
|
// <copyright file="Relationship.cs" company="Microsoft">
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
//
|
|
// @owner Microsoft
|
|
// @backupOwner Microsoft
|
|
//---------------------------------------------------------------------
|
|
|
|
namespace System.Data.EntityModel.SchemaObjectModel
|
|
{
|
|
using System.Collections.Generic;
|
|
using System.Data.Metadata.Edm;
|
|
using System.Data.Objects.DataClasses;
|
|
using System.Diagnostics;
|
|
using System.Xml;
|
|
|
|
/// <summary>
|
|
/// Represents an Association element
|
|
/// </summary>
|
|
internal sealed class Relationship : SchemaType, IRelationship
|
|
{
|
|
private RelationshipKind _relationshipKind;
|
|
private RelationshipEndCollection _ends;
|
|
private List<ReferentialConstraint> _constraints;
|
|
private bool _isForeignKey;
|
|
|
|
/// <summary>
|
|
/// Construct a Relationship object
|
|
/// </summary>
|
|
/// <param name="parent">the parent</param>
|
|
/// <param name="kind">the kind of relationship</param>
|
|
public Relationship(Schema parent, RelationshipKind kind)
|
|
: base(parent)
|
|
{
|
|
RelationshipKind = kind;
|
|
|
|
if (Schema.DataModel == SchemaDataModelOption.EntityDataModel)
|
|
{
|
|
_isForeignKey = false;
|
|
OtherContent.Add(Schema.SchemaSource);
|
|
}
|
|
else if (Schema.DataModel == SchemaDataModelOption.ProviderDataModel)
|
|
{
|
|
_isForeignKey = true;
|
|
}
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// List of Ends defined for this Association
|
|
/// </summary>
|
|
public IList<IRelationshipEnd> Ends
|
|
{
|
|
get
|
|
{
|
|
if ( _ends == null )
|
|
_ends = new RelationshipEndCollection();
|
|
return _ends;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the list of constraints on this relation
|
|
/// </summary>
|
|
public IList<ReferentialConstraint> Constraints
|
|
{
|
|
get
|
|
{
|
|
if (_constraints == null)
|
|
{
|
|
_constraints = new List<ReferentialConstraint>();
|
|
}
|
|
return _constraints;
|
|
}
|
|
}
|
|
|
|
public bool TryGetEnd( string roleName, out IRelationshipEnd end )
|
|
{
|
|
return _ends.TryGetEnd( roleName, out end );
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Is this an Association
|
|
/// </summary>
|
|
public RelationshipKind RelationshipKind
|
|
{
|
|
get
|
|
{
|
|
return _relationshipKind;
|
|
}
|
|
private set
|
|
{
|
|
_relationshipKind = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Is this a foreign key (aka foreign key) relationship?
|
|
/// </summary>
|
|
public bool IsForeignKey
|
|
{
|
|
get { return _isForeignKey; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// do whole element validation
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
internal override void Validate()
|
|
{
|
|
base.Validate();
|
|
|
|
bool foundOperations = false;
|
|
foreach ( RelationshipEnd end in Ends )
|
|
{
|
|
end.Validate();
|
|
if ( RelationshipKind == RelationshipKind.Association )
|
|
{
|
|
if ( end.Operations.Count > 0 )
|
|
{
|
|
if ( foundOperations )
|
|
end.AddError( ErrorCode.InvalidOperation, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.InvalidOperationMultipleEndsInAssociation);
|
|
foundOperations = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Constraints.Count == 0)
|
|
{
|
|
if (this.Schema.DataModel == SchemaDataModelOption.ProviderDataModel)
|
|
{
|
|
AddError(ErrorCode.MissingConstraintOnRelationshipType,
|
|
EdmSchemaErrorSeverity.Error,
|
|
System.Data.Entity.Strings.MissingConstraintOnRelationshipType(FQName));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (ReferentialConstraint constraint in Constraints)
|
|
{
|
|
constraint.Validate();
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// do whole element resolution
|
|
/// </summary>
|
|
internal override void ResolveTopLevelNames()
|
|
{
|
|
base.ResolveTopLevelNames();
|
|
|
|
foreach ( RelationshipEnd end in Ends )
|
|
end.ResolveTopLevelNames();
|
|
|
|
foreach (ReferentialConstraint referentialConstraint in Constraints)
|
|
{
|
|
referentialConstraint.ResolveTopLevelNames();
|
|
}
|
|
}
|
|
|
|
protected override bool HandleElement(XmlReader reader)
|
|
{
|
|
if (base.HandleElement(reader))
|
|
{
|
|
return true;
|
|
}
|
|
else if (CanHandleElement(reader, XmlConstants.End))
|
|
{
|
|
HandleEndElement(reader);
|
|
return true;
|
|
}
|
|
else if (CanHandleElement(reader, XmlConstants.ReferentialConstraint))
|
|
{
|
|
HandleConstraintElement(reader);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// handle the End child element
|
|
/// </summary>
|
|
/// <param name="reader">XmlReader positioned at the end element</param>
|
|
private void HandleEndElement(XmlReader reader)
|
|
{
|
|
Debug.Assert(reader != null);
|
|
RelationshipEnd end = new RelationshipEnd(this);
|
|
end.Parse(reader);
|
|
|
|
if (Ends.Count == 2)
|
|
{
|
|
AddError( ErrorCode.InvalidAssociation, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.TooManyAssociationEnds(FQName ) );
|
|
return;
|
|
}
|
|
|
|
Ends.Add(end);
|
|
}
|
|
|
|
/// <summary>
|
|
/// handle the constraint element
|
|
/// </summary>
|
|
/// <param name="reader">XmlReader positioned at the constraint element</param>
|
|
private void HandleConstraintElement(XmlReader reader)
|
|
{
|
|
Debug.Assert(reader != null);
|
|
|
|
ReferentialConstraint constraint = new ReferentialConstraint(this);
|
|
constraint.Parse(reader);
|
|
this.Constraints.Add(constraint);
|
|
|
|
if (this.Schema.DataModel == SchemaDataModelOption.EntityDataModel && this.Schema.SchemaVersion >= XmlConstants.EdmVersionForV2)
|
|
{
|
|
// in V2, referential constraint implies foreign key
|
|
_isForeignKey = true;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|