|
|
|
@ -43,7 +43,8 @@ namespace Marr.Data
|
|
|
|
|
private GroupingKeyCollection _groupingKeyColumns;
|
|
|
|
|
private Dictionary<string, EntityReference> _entityReferences;
|
|
|
|
|
|
|
|
|
|
public IList RootList { get; private set; }
|
|
|
|
|
internal IList RootList { get; private set; }
|
|
|
|
|
internal bool IsParentReference { get; private set; }
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Recursively builds an entity graph of the given parent type.
|
|
|
|
@ -68,12 +69,22 @@ namespace Marr.Data
|
|
|
|
|
_entityType = entityType;
|
|
|
|
|
_parent = parent;
|
|
|
|
|
_relationship = relationship;
|
|
|
|
|
_columns = _repos.GetColumns(entityType);
|
|
|
|
|
IsParentReference = !IsRoot && AnyParentsAreOfType(entityType);
|
|
|
|
|
if (!IsParentReference)
|
|
|
|
|
{
|
|
|
|
|
_columns = _repos.GetColumns(entityType);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_relationships = _repos.GetRelationships(entityType);
|
|
|
|
|
_children = new List<EntityGraph>();
|
|
|
|
|
Member = relationship != null ? relationship.Member : null;
|
|
|
|
|
_entityReferences = new Dictionary<string, EntityReference>();
|
|
|
|
|
|
|
|
|
|
if (IsParentReference)
|
|
|
|
|
{
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Create a new EntityGraph for each child relationship that is not lazy loaded
|
|
|
|
|
foreach (Relationship childRelationship in this.Relationships)
|
|
|
|
|
{
|
|
|
|
@ -183,53 +194,14 @@ namespace Marr.Data
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Initializes the owning lists on many-to-many Children.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="entityInstance"></param>
|
|
|
|
|
private void InitOneToManyChildLists(EntityReference entityRef)
|
|
|
|
|
{
|
|
|
|
|
// Get a reference to the parent's the childrens' OwningLists to the parent entity
|
|
|
|
|
for (int i = 0; i < Relationships.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
Relationship relationship = Relationships[i];
|
|
|
|
|
if (relationship.RelationshipInfo.RelationType == RelationshipTypes.Many)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
IList list = (IList)_repos.ReflectionStrategy.CreateInstance(relationship.MemberType);
|
|
|
|
|
_repos.ReflectionStrategy.SetFieldValue(entityRef.Entity, relationship.Member.Name, list);
|
|
|
|
|
|
|
|
|
|
// Save a reference to each 1-M list
|
|
|
|
|
entityRef.AddChildList(relationship.Member.Name, list);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
throw new DataMappingException(
|
|
|
|
|
string.Format("{0}.{1} is a \"Many\" relationship type so it must derive from IList.",
|
|
|
|
|
entityRef.Entity.GetType().Name, relationship.Member.Name),
|
|
|
|
|
ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Recursively adds primary key columns from contiguous child graphs with a one-to-one relationship type to the pKeys collection..
|
|
|
|
|
/// Searches for a previously loaded parent entity and then sets that reference to the mapped Relationship property.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="pKeys"></param>
|
|
|
|
|
/// <param name="entity"></param>
|
|
|
|
|
private void AddOneToOneChildKeys(ColumnMapCollection pKeys, EntityGraph entity)
|
|
|
|
|
public void AddParentReference()
|
|
|
|
|
{
|
|
|
|
|
var oneToOneChildren = entity.Children
|
|
|
|
|
.Where(c => c._relationship.RelationshipInfo.RelationType == RelationshipTypes.One);
|
|
|
|
|
|
|
|
|
|
foreach (var child in oneToOneChildren)
|
|
|
|
|
{
|
|
|
|
|
pKeys.AddRange(child.Columns.PrimaryKeys);
|
|
|
|
|
AddOneToOneChildKeys(pKeys, child);
|
|
|
|
|
}
|
|
|
|
|
var parentReference = FindParentReference();
|
|
|
|
|
_repos.ReflectionStrategy.SetFieldValue(_parent._entity, _relationship.Member.Name, parentReference);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Concatenates the values of the GroupingKeys property and compares them
|
|
|
|
|
/// against the LastKeyGroup property. Returns true if the values are different,
|
|
|
|
@ -247,7 +219,7 @@ namespace Marr.Data
|
|
|
|
|
|
|
|
|
|
// Concatenate column values
|
|
|
|
|
KeyGroupInfo keyGroupInfo = groupingKeyColumns.CreateGroupingKey(reader);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!keyGroupInfo.HasNullKey && !_entityReferences.ContainsKey(keyGroupInfo.GroupingKey))
|
|
|
|
|
{
|
|
|
|
|
isNewGroup = true;
|
|
|
|
@ -255,7 +227,7 @@ namespace Marr.Data
|
|
|
|
|
|
|
|
|
|
return isNewGroup;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets the GroupingKeys for this entity.
|
|
|
|
|
/// GroupingKeys determine when to create and add a new entity to the graph.
|
|
|
|
@ -278,6 +250,68 @@ namespace Marr.Data
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private bool AnyParentsAreOfType(Type type)
|
|
|
|
|
{
|
|
|
|
|
EntityGraph parent = _parent;
|
|
|
|
|
while (parent != null)
|
|
|
|
|
{
|
|
|
|
|
if (parent._entityType == type)
|
|
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
parent = parent._parent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private object FindParentReference()
|
|
|
|
|
{
|
|
|
|
|
var parent = this.Parent.Parent;
|
|
|
|
|
while (parent != null)
|
|
|
|
|
{
|
|
|
|
|
if (parent._entityType == _relationship.MemberType)
|
|
|
|
|
{
|
|
|
|
|
return parent._entity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parent = parent.Parent;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Initializes the owning lists on many-to-many Children.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="entityInstance"></param>
|
|
|
|
|
private void InitOneToManyChildLists(EntityReference entityRef)
|
|
|
|
|
{
|
|
|
|
|
// Get a reference to the parent's the childrens' OwningLists to the parent entity
|
|
|
|
|
for (int i = 0; i < Relationships.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
Relationship relationship = Relationships[i];
|
|
|
|
|
if (relationship.RelationshipInfo.RelationType == RelationshipTypes.Many)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
IList list = (IList)_repos.ReflectionStrategy.CreateInstance(relationship.MemberType);
|
|
|
|
|
_repos.ReflectionStrategy.SetFieldValue(entityRef.Entity, relationship.Member.Name, list);
|
|
|
|
|
|
|
|
|
|
// Save a reference to each 1-M list
|
|
|
|
|
entityRef.AddChildList(relationship.Member.Name, list);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
throw new DataMappingException(
|
|
|
|
|
string.Format("{0}.{1} is a \"Many\" relationship type so it must derive from IList.",
|
|
|
|
|
entityRef.Entity.GetType().Name, relationship.Member.Name),
|
|
|
|
|
ex);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Gets a list of keys to group by.
|
|
|
|
|
/// </summary>
|
|
|
|
@ -373,4 +407,4 @@ public struct KeyGroupInfo
|
|
|
|
|
{
|
|
|
|
|
get { return _hasNullKey; }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|