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;
_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)
{
@ -182,6 +193,94 @@ namespace Marr.Data
InitOneToManyChildLists(entityRef);
}
/// <summary>
/// Searches for a previously loaded parent entity and then sets that reference to the mapped Relationship property.
/// </summary>
public void AddParentReference()
{
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,
/// or false if the values are the same.
/// The currently concatenated keys are saved in the LastKeyGroup property.
/// </summary>
/// <param name="reader"></param>
/// <returns></returns>
public bool IsNewGroup(DbDataReader reader)
{
bool isNewGroup = false;
// Get primary keys from parent entity and any one-to-one child entites
GroupingKeyCollection groupingKeyColumns = this.GroupingKeyColumns;
// Concatenate column values
KeyGroupInfo keyGroupInfo = groupingKeyColumns.CreateGroupingKey(reader);
if (!keyGroupInfo.HasNullKey && !_entityReferences.ContainsKey(keyGroupInfo.GroupingKey))
{
isNewGroup = true;
}
return isNewGroup;
}
/// <summary>
/// Gets the GroupingKeys for this entity.
/// GroupingKeys determine when to create and add a new entity to the graph.
/// </summary>
/// <remarks>
/// A simple entity with no relationships will return only its PrimaryKey columns.
/// A parent entity with one-to-one child relationships will include its own PrimaryKeys,
/// and it will recursively traverse all Children with one-to-one relationships and add their PrimaryKeys.
/// A child entity that has a one-to-one relationship with its parent will use the same
/// GroupingKeys already defined by its parent.
/// </remarks>
public GroupingKeyCollection GroupingKeyColumns
{
get
{
if (_groupingKeyColumns == null)
_groupingKeyColumns = GetGroupingKeyColumns();
return _groupingKeyColumns;
}
}
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>
@ -213,71 +312,6 @@ namespace Marr.Data
}
}
/// <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);
}
}
/// <summary>
/// Concatenates the values of the GroupingKeys property and compares them
/// against the LastKeyGroup property. Returns true if the values are different,
/// or false if the values are the same.
/// The currently concatenated keys are saved in the LastKeyGroup property.
/// </summary>
/// <param name="reader"></param>
/// <returns></returns>
public bool IsNewGroup(DbDataReader reader)
{
bool isNewGroup = false;
// Get primary keys from parent entity and any one-to-one child entites
GroupingKeyCollection groupingKeyColumns = this.GroupingKeyColumns;
// Concatenate column values
KeyGroupInfo keyGroupInfo = groupingKeyColumns.CreateGroupingKey(reader);
if (!keyGroupInfo.HasNullKey && !_entityReferences.ContainsKey(keyGroupInfo.GroupingKey))
{
isNewGroup = true;
}
return isNewGroup;
}
/// <summary>
/// Gets the GroupingKeys for this entity.
/// GroupingKeys determine when to create and add a new entity to the graph.
/// </summary>
/// <remarks>
/// A simple entity with no relationships will return only its PrimaryKey columns.
/// A parent entity with one-to-one child relationships will include its own PrimaryKeys,
/// and it will recursively traverse all Children with one-to-one relationships and add their PrimaryKeys.
/// A child entity that has a one-to-one relationship with its parent will use the same
/// GroupingKeys already defined by its parent.
/// </remarks>
public GroupingKeyCollection GroupingKeyColumns
{
get
{
if (_groupingKeyColumns == null)
_groupingKeyColumns = GetGroupingKeyColumns();
return _groupingKeyColumns;
}
}
/// <summary>
/// Gets a list of keys to group by.
/// </summary>
@ -373,4 +407,4 @@ public struct KeyGroupInfo
{
get { return _hasNullKey; }
}
}
}

View File

@ -54,7 +54,7 @@ namespace Marr.Data
// Register a default IReflectionStrategy
ReflectionStrategy = new CachedReflectionStrategy();
// Register a default type converter for Enums
TypeConverters.Add(typeof(Enum), new Converters.EnumStringConverter());
@ -180,7 +180,7 @@ namespace Marr.Data
return Relationships[type];
}
#endregion
#region - Reflection Strategy -

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>