I have a tree hierarchy Eg. Community > Building > Floor > Apartment > .. in a relational database where starting from left to right, they have one to many relationship.
Now, I want to be able to copy any level of the hierarchy to another (matching)node in the tree and I have come up with two approaches and would appreciate any feedback on the advantages/disadvantages of each.
Approach # 1
public abstract class GenericItem
{
public int ItemID { get; set; }
public abstract int ItemType { get; }
public string ItemName { get; set; }
public string LocationPath { get; set; }
public GenericItem Parent { get; set; }
private SqlConnection _DBConn;
public SqlConnection DBConn
{
get
{
if (_DBConn.IsNull())
_DBConn = Parent.DBConn;
return _DBConn;
}
set
{
_DBConn = value;
}
}
private IEnumerable<GenericItem> _Children;
public IEnumerable<GenericItem> Children
{
get
{
return _Children.IfNull(GetChildren());
}
}
/// <summary>
/// Creates a deep copy of itself and the children recursively
/// </summary>
protected void DeepCopyToParent(GenericItem newParent)
{
// Get a reference to the copy of this item, to which all the children will be copied to
var copyParent = CopyMeToParent(newParent);
foreach (var child in Children)
{
child.DeepCopyToParent(newParent);
}
}
/// <summary>
/// Copies this object and/or its descendants
/// </summary>
/// <param name="copyTarget">A GenericItem where this object needs to be copied. It can be either the of the same ItemType as the object or its parent type</param>
/// <param name="deepCopy">Specifies whether to copy the entire hierarchy or just this object</param>
public void CopyTo(GenericItem copyTarget)
{
// Only accept the item type or parent item type
// Make sure that the hierarchy is copied in its entirety
using (var tranScope = new TransactionScope())
{
DeepCopyToParent(copyTarget);
tranScope.Complete();
}
}
/// <summary>
/// Gets all the immediate descendants of the current item
/// </summary>
/// <returns></returns>
protected abstract IEnumerable<GenericItem> GetChildren();
public abstract IEnumerable<GenericItem> GetSiblings();
public abstract IEnumerable<GenericItem> GetSiblingsAndCousins();
/// <summary>
/// Copies only this object to the supplied parent object
/// </summary>
/// <param name="newParent"></param>
/// <returns></returns>
protected abstract GenericItem CopyMeToParent(GenericItem newParent);
}
public class Community : GenericItem
{
public override int ItemType
{
get
{
return 1;
}
}
public override IEnumerable<GenericItem> GetSiblings()
{
// Query the database and return the results
}
public override IEnumerable<GenericItem> GetSiblingsAndCousins()
{
// Query the database and return the results
}
protected override GenericItem CopyMeToParent(GenericItem newParent)
{
// Query the database and return the results
}
protected override IEnumerable<GenericItem> GetChildren()
{
// Query the database and return the results
}
}
Approach # 2
public class GenericItem
{
public int ItemID { get; set; }
public abstract int ItemType { get; }
public string ItemName { get; set; }
public string LocationPath { get; set; }
public GenericItem Parent { get; set; }
private SqlConnection _DBConn;
public SqlConnection DBConn
{
get
{
if (_DBConn.IsNull())
_DBConn = Parent.DBConn;
return _DBConn;
}
set
{
_DBConn = value;
}
}
private IEnumerable<GenericItem> _Children;
public IEnumerable<GenericItem> Children
{
get
{
return _Children.IfNull(GetChildren());
}
}
/// <summary>
/// Creates a deep copy of itself and the children recursively
/// </summary>
protected void DeepCopyToParent(GenericItem newParent)
{
// Get a reference to the copy of this item, to which all the children will be copied to
var copyParent = CopyMeToParent(newParent);
foreach (var child in Children)
{
child.DeepCopyToParent(newParent);
}
}
/// <summary>
/// Copies this object and/or its descendants
/// </summary>
/// <param name="copyTarget">A GenericItem where this object needs to be copied. It can be either the of the same ItemType as the object or its parent type</param>
/// <param name="deepCopy">Specifies whether to copy the entire hierarchy or just this object</param>
public void CopyTo(GenericItem copyTarget)
{
// Only accept the item type or parent item type
// Make sure that the hierarchy is copied in its entirety
using (var tranScope = new TransactionScope())
{
DeepCopyToParent(copyTarget);
tranScope.Complete();
}
}
/// <summary>
/// Gets all the immediate descendants of the current item
/// </summary>
/// <returns></returns>
protected abstract IEnumerable<GenericItem> GetChildren()
{
// Query a stored procedure which returns different items based on supplied parameters
}
public abstract IEnumerable<GenericItem> GetSiblings()
{
// Query a stored procedure which returns different items based on supplied parameters
}
public abstract IEnumerable<GenericItem> GetSiblingsAndCousins()
{
// Query a stored procedure which returns different items based on supplied parameters
}
/// <summary>
/// Copies only this object to the supplied parent object
/// </summary>
/// <param name="newParent"></param>
/// <returns></returns>
protected abstract GenericItem CopyMeToParent(GenericItem newParent)
{
// A generic stored procedure which copies different item types
}
}
My arguments for each: With the first approach(Composite Design Pattern), I get the flexibility of further extension, but also, if my hierarchy increases in depth with new type, I will have a lot of classes.
With the second approach, I just have to keep adding to the generic stored procs without worrying about refactoring C# code in multiple places, however, I lose the flexibility.
Please provide reasons for choosing one over the other and if you think both of these are bad implementations, feel free to do so.
Aucun commentaire:
Enregistrer un commentaire