Synced Marr with upstream

This commit is contained in:
Keivan Beigi 2013-05-02 11:14:54 -07:00
parent 96990eabb3
commit 16425cdab6
4 changed files with 113 additions and 79 deletions

View File

@ -660,15 +660,19 @@ namespace Marr.Data
// and multiple entities are created from each view record.
foreach (EntityGraph lvl in graph)
{
// If is child relationship entity, and childrenToLoad are specified, and entity is not listed,
// then skip this entity.
if (childrenToLoad.Count > 0 && !lvl.IsRoot && !childrenToLoad.ContainsMember(lvl.Member)) // lvl.Member.Name
if (lvl.IsParentReference)
{
// A child specified a circular reference to its previously loaded parent
lvl.AddParentReference();
}
else if (childrenToLoad.Count > 0 && !lvl.IsRoot && !childrenToLoad.ContainsMember(lvl.Member))
{
// A list of relationships-to-load was specified and this relationship was not included
continue;
}
if (lvl.IsNewGroup(reader))
else if (lvl.IsNewGroup(reader))
{
// Create a new entity with the data reader
var newEntity = mappingHelper.CreateAndLoadEntity(lvl.EntityType, lvl.Columns, reader, true);
// Add entity to the appropriate place in the object graph

View File

@ -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;
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,51 +194,12 @@ namespace Marr.Data
}
/// <summary>
/// Initializes the owning lists on many-to-many Children.
/// Searches for a previously loaded parent entity and then sets that reference to the mapped Relationship property.
/// </summary>
/// <param name="entityInstance"></param>
private void InitOneToManyChildLists(EntityReference entityRef)
public void AddParentReference()
{
// 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..
/// </summary>
/// <param name="pKeys"></param>
/// <param name="entity"></param>
private void AddOneToOneChildKeys(ColumnMapCollection pKeys, EntityGraph entity)
{
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>
@ -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>

View File

@ -12,10 +12,6 @@
<AssemblyName>Marr.Data</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SccProjectName>SAK</SccProjectName>
<SccLocalPath>SAK</SccLocalPath>
<SccAuxPath>SAK</SccAuxPath>
<SccProvider>SAK</SccProvider>
<FileUpgradeFlags>
</FileUpgradeFlags>
<OldToolsVersion>3.5</OldToolsVersion>