Synced Marr with upstream
This commit is contained in:
parent
96990eabb3
commit
16425cdab6
|
@ -660,15 +660,19 @@ namespace Marr.Data
|
||||||
// and multiple entities are created from each view record.
|
// and multiple entities are created from each view record.
|
||||||
foreach (EntityGraph lvl in graph)
|
foreach (EntityGraph lvl in graph)
|
||||||
{
|
{
|
||||||
// If is child relationship entity, and childrenToLoad are specified, and entity is not listed,
|
if (lvl.IsParentReference)
|
||||||
// then skip this entity.
|
|
||||||
if (childrenToLoad.Count > 0 && !lvl.IsRoot && !childrenToLoad.ContainsMember(lvl.Member)) // lvl.Member.Name
|
|
||||||
{
|
{
|
||||||
|
// 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;
|
continue;
|
||||||
}
|
}
|
||||||
|
else if (lvl.IsNewGroup(reader))
|
||||||
if (lvl.IsNewGroup(reader))
|
|
||||||
{
|
{
|
||||||
|
// Create a new entity with the data reader
|
||||||
var newEntity = mappingHelper.CreateAndLoadEntity(lvl.EntityType, lvl.Columns, reader, true);
|
var newEntity = mappingHelper.CreateAndLoadEntity(lvl.EntityType, lvl.Columns, reader, true);
|
||||||
|
|
||||||
// Add entity to the appropriate place in the object graph
|
// Add entity to the appropriate place in the object graph
|
||||||
|
|
|
@ -43,7 +43,8 @@ namespace Marr.Data
|
||||||
private GroupingKeyCollection _groupingKeyColumns;
|
private GroupingKeyCollection _groupingKeyColumns;
|
||||||
private Dictionary<string, EntityReference> _entityReferences;
|
private Dictionary<string, EntityReference> _entityReferences;
|
||||||
|
|
||||||
public IList RootList { get; private set; }
|
internal IList RootList { get; private set; }
|
||||||
|
internal bool IsParentReference { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Recursively builds an entity graph of the given parent type.
|
/// Recursively builds an entity graph of the given parent type.
|
||||||
|
@ -68,12 +69,22 @@ namespace Marr.Data
|
||||||
_entityType = entityType;
|
_entityType = entityType;
|
||||||
_parent = parent;
|
_parent = parent;
|
||||||
_relationship = relationship;
|
_relationship = relationship;
|
||||||
_columns = _repos.GetColumns(entityType);
|
IsParentReference = !IsRoot && AnyParentsAreOfType(entityType);
|
||||||
|
if (!IsParentReference)
|
||||||
|
{
|
||||||
|
_columns = _repos.GetColumns(entityType);
|
||||||
|
}
|
||||||
|
|
||||||
_relationships = _repos.GetRelationships(entityType);
|
_relationships = _repos.GetRelationships(entityType);
|
||||||
_children = new List<EntityGraph>();
|
_children = new List<EntityGraph>();
|
||||||
Member = relationship != null ? relationship.Member : null;
|
Member = relationship != null ? relationship.Member : null;
|
||||||
_entityReferences = new Dictionary<string, EntityReference>();
|
_entityReferences = new Dictionary<string, EntityReference>();
|
||||||
|
|
||||||
|
if (IsParentReference)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Create a new EntityGraph for each child relationship that is not lazy loaded
|
// Create a new EntityGraph for each child relationship that is not lazy loaded
|
||||||
foreach (Relationship childRelationship in this.Relationships)
|
foreach (Relationship childRelationship in this.Relationships)
|
||||||
{
|
{
|
||||||
|
@ -182,6 +193,94 @@ namespace Marr.Data
|
||||||
InitOneToManyChildLists(entityRef);
|
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>
|
/// <summary>
|
||||||
/// Initializes the owning lists on many-to-many Children.
|
/// Initializes the owning lists on many-to-many Children.
|
||||||
/// </summary>
|
/// </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>
|
/// <summary>
|
||||||
/// Gets a list of keys to group by.
|
/// Gets a list of keys to group by.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -373,4 +407,4 @@ public struct KeyGroupInfo
|
||||||
{
|
{
|
||||||
get { return _hasNullKey; }
|
get { return _hasNullKey; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace Marr.Data
|
||||||
|
|
||||||
// Register a default IReflectionStrategy
|
// Register a default IReflectionStrategy
|
||||||
ReflectionStrategy = new CachedReflectionStrategy();
|
ReflectionStrategy = new CachedReflectionStrategy();
|
||||||
|
|
||||||
// Register a default type converter for Enums
|
// Register a default type converter for Enums
|
||||||
TypeConverters.Add(typeof(Enum), new Converters.EnumStringConverter());
|
TypeConverters.Add(typeof(Enum), new Converters.EnumStringConverter());
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ namespace Marr.Data
|
||||||
|
|
||||||
return Relationships[type];
|
return Relationships[type];
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region - Reflection Strategy -
|
#region - Reflection Strategy -
|
||||||
|
|
|
@ -12,10 +12,6 @@
|
||||||
<AssemblyName>Marr.Data</AssemblyName>
|
<AssemblyName>Marr.Data</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<SccProjectName>SAK</SccProjectName>
|
|
||||||
<SccLocalPath>SAK</SccLocalPath>
|
|
||||||
<SccAuxPath>SAK</SccAuxPath>
|
|
||||||
<SccProvider>SAK</SccProvider>
|
|
||||||
<FileUpgradeFlags>
|
<FileUpgradeFlags>
|
||||||
</FileUpgradeFlags>
|
</FileUpgradeFlags>
|
||||||
<OldToolsVersion>3.5</OldToolsVersion>
|
<OldToolsVersion>3.5</OldToolsVersion>
|
||||||
|
|
Loading…
Reference in New Issue