Skip to content

Instantly share code, notes, and snippets.

@jeremylcarter
Created November 6, 2014 03:39
Show Gist options
  • Save jeremylcarter/f9ffce5979d9d9036faa to your computer and use it in GitHub Desktop.
Save jeremylcarter/f9ffce5979d9d9036faa to your computer and use it in GitHub Desktop.
public class ColumnInfo {
...
...
...
public bool OneToOneColumn { get; set; }
public bool OneToManyColumn { get; set; }
public bool LazyLoad { get; set; }
public static ColumnInfo FromMemberInfo(MemberInfo mi)
{
var ci = new ColumnInfo();
var attrs = mi.GetCustomAttributes(true);
var colAttrs = attrs.OfType<ColumnAttribute>();
var columnTypeAttrs = attrs.OfType<ColumnTypeAttribute>();
var ignoreAttrs = attrs.OfType<IgnoreAttribute>();
var oneToOne = attrs.OfType<OneToOneAttribute>();
var oneToMany = attrs.OfType<OneToManyAttribute>();
// Check if declaring poco has [ExplicitColumns] attribute
var explicitColumns = mi.DeclaringType.GetCustomAttributes(typeof(ExplicitColumnsAttribute), true).Any();
var aliasColumn = (AliasAttribute) mi.GetCustomAttributes(typeof (AliasAttribute), true).FirstOrDefault();
// Ignore column if declarying poco has [ExplicitColumns] attribute
// and property doesn't have an explicit [Column] attribute,
// or property has an [Ignore] attribute
if ((explicitColumns && !colAttrs.Any()) || ignoreAttrs.Any())
{
ci.IgnoreColumn = true;
}
// Try to detect relationship columns
try
{
if (oneToOne != null && !colAttrs.Any() && oneToOne.Any())
{
if (oneToOne.FirstOrDefault() != null)
{
ci.ForeignKeyName = oneToOne.FirstOrDefault().Column;
}
if (oneToOne.FirstOrDefault().LazyLoad == true)
{
ci.LazyLoad = true;
}
ci.IgnoreColumn = true;
ci.OneToOneColumn = true;
}
if (oneToMany != null && !colAttrs.Any() && oneToMany.Any())
{
if (oneToMany.FirstOrDefault() != null)
{
ci.ForeignKeyName = oneToMany.FirstOrDefault().Column;
}
if (oneToMany.FirstOrDefault().LazyLoad == true)
{
ci.LazyLoad = true;
}
ci.IgnoreColumn = true;
ci.OneToManyColumn = true;
}
}
catch (Exception)
{
}
// Read attribute
if (colAttrs.Any())
{
var colattr = colAttrs.First();
ci.ColumnName = colattr.Name ?? mi.Name;
ci.ForceToUtc = colattr.ForceToUtc;
ci.ResultColumn = colattr is ResultColumnAttribute;
ci.VersionColumn = colattr is VersionColumnAttribute;
ci.ComputedColumn = colattr is ComputedColumnAttribute;
ci.ColumnAlias = aliasColumn != null ? aliasColumn.Alias : null;
}
else
{
ci.ColumnName = mi.Name;
}
if (columnTypeAttrs.Any())
{
ci.ColumnType = columnTypeAttrs.First().Type;
}
return ci;
}
}
public List<T1> FetchAndInclude<T1>(Expression<Func<T1, bool>> expression, bool lazyLoad = true)
{
if (this.LazyLoading | lazyLoad)
{
var pd = PocoDataFactory.ForType(typeof(T1));
var members = pd.RelationshipColumns;
if (members.Count != 0 && members.Count(i => i.Value.LazyLoad) != 0)
{
return FetchAndInclude<T1>(expression, members.Select(i => i.Value.ColumnType));
}
}
return FetchWhere<T1>(expression);
}
internal List<T1> FetchAndInclude<T1, T2>(string sql, object[] para)
{
var pd = PocoDataFactory.ForType(typeof(T1));
var members = pd.RelationshipColumns;
if (members.Count != 0)
{
var resultSet = Fetch<T1>(sql,para);
if (resultSet != null && members.Any())
{
foreach (var member in members)
{
var relationshipColumn = member.Value;
var foreignKey = relationshipColumn.ForeignKeyName;
// cache the underlying type from the database
Dictionary<object, T2> itemCache = new Dictionary<object, T2>();
foreach (var resultItem in resultSet)
{
try
{
var foreignKeyObject = resultItem.GetProperty(foreignKey);
if (foreignKeyObject != null)
{
if (!itemCache.ContainsKey(foreignKeyObject))
{
var resultQuery = SingleOrDefaultById<T2>(foreignKeyObject);
itemCache.Add(foreignKeyObject, resultQuery);
relationshipColumn.SetValue(resultItem, resultQuery);
}
else
{
relationshipColumn.SetValue(resultItem, itemCache[foreignKeyObject]);
}
}
}
catch (Exception)
{
}
}
itemCache.Clear();
itemCache = null;
}
}
return resultSet;
}
return Fetch<T1>(sql, para);
}
private List<T1> FetchAndInclude<T1>(Expression<Func<T1, bool>> expression, IEnumerable<Type> types)
{
if (types != null && types.Any())
{
var pd = PocoDataFactory.ForType(typeof(T1));
var members = pd.RelationshipColumns.Where(i => i.Value.ColumnType.In(types));
List<T1> resultSet = null;
if (expression == null)
{
resultSet = Fetch<T1>();
}
else
{
resultSet = FetchWhere<T1>(expression);
}
if (resultSet != null)
{
foreach (var member in members)
{
try
{
var memberType = member.Value.ColumnType;
var relationshipColumn = member.Value;
var foreignKey = relationshipColumn.ForeignKeyName;
// cache the underlying type from the database
Dictionary<object, object> itemCache = new Dictionary<object, object>();
foreach (var resultItem in resultSet)
{
try
{
if (!member.Value.IsGeneric)
{
var foreignKeyObject = resultItem.GetProperty(foreignKey);
if (foreignKeyObject != null)
{
if (!itemCache.ContainsKey(foreignKeyObject))
{
MethodInfo method = GetType().GetMethod("SingleOrDefaultById")
.MakeGenericMethod(new Type[] {memberType});
var resultQuery = method.Invoke(this, new object[] {foreignKeyObject});
itemCache.Add(foreignKeyObject, resultQuery);
relationshipColumn.SetValue(resultItem, resultQuery);
}
else
{
relationshipColumn.SetValue(resultItem, itemCache[foreignKeyObject]);
}
}
}
else
{
var foreignKeyObject = resultItem.GetProperty(pd.TableInfo.PrimaryKey);
if (foreignKeyObject != null)
{
if (!itemCache.ContainsKey(foreignKeyObject))
{
// Enumerable
var baseType = member.Value.ColumnType.GetGenericArguments()[0];
var md = PocoDataFactory.ForType(baseType);
List<MethodInfo> methods =
GetType()
.GetMethods()
.Where(i => i.Name == "Fetch")
.Where(m => m.GetGenericArguments().Length == 1)
.Where(m => m.GetParameters().Length == 2).ToList();
var method =
methods.FirstOrDefault().MakeGenericMethod(new Type[] {baseType});
var sqlSelect = AutoSelectHelper.SimpleSelect(this, md, foreignKey,
foreignKeyObject);
var resultQuery = method.Invoke(this, new object[] {sqlSelect, null});
itemCache.Add(foreignKeyObject, resultQuery);
relationshipColumn.SetValue(resultItem, resultQuery);
}
else
{
relationshipColumn.SetValue(resultItem, itemCache[foreignKeyObject]);
}
}
}
}
catch (Exception)
{
}
}
itemCache.Clear();
itemCache = null;
}
catch (Exception)
{
}
}
}
return resultSet;
}
return FetchWhere<T1>(expression);
}
public List<T1> FetchAndInclude<T1, T2>(Expression<Func<T1, bool>> expression)
{
var pd = PocoDataFactory.ForType(typeof(T1));
var members = pd.RelationshipColumns;
if (members.Count != 0)
{
var resultSet = FetchWhere<T1>(expression);
if (resultSet != null && members.Any())
{
foreach (var member in members)
{
var relationshipColumn = member.Value;
var foreignKey = relationshipColumn.ForeignKeyName;
// cache the underlying type from the database
Dictionary<object, T2> itemCache = new Dictionary<object, T2>();
foreach (var resultItem in resultSet)
{
try
{
var foreignKeyObject = resultItem.GetProperty(foreignKey);
if (foreignKeyObject != null)
{
if (!itemCache.ContainsKey(foreignKeyObject))
{
var resultQuery = SingleOrDefaultById<T2>(foreignKeyObject);
itemCache.Add(foreignKeyObject, resultQuery);
relationshipColumn.SetValue(resultItem, resultQuery);
}
else
{
relationshipColumn.SetValue(resultItem, itemCache[foreignKeyObject]);
}
}
}
catch (Exception)
{
}
}
itemCache.Clear();
itemCache = null;
}
}
return resultSet;
}
return FetchWhere<T1>(expression);
}
public Dictionary<string, RelationshipColumn> RelationshipColumns { get; protected internal set; }
public PocoData(Type t, IMapper mapper)
: this()
{
.... ....
....
....
RelationshipColumns = new Dictionary<string, RelationshipColumn>(StringComparer.OrdinalIgnoreCase);
ColumnInfo ci = ColumnInfo.FromMemberInfo(mi);
if (ci.IgnoreColumn)
{
if (ci.LazyLoad | ci.OneToManyColumn | ci.OneToOneColumn)
{
// Relationship column
var rc = new RelationshipColumn();
rc.TableInfo = TableInfo;
rc.MemberInfo = mi;
rc.ColumnName = ci.ColumnName;
rc.ForeignKeyName = ci.ForeignKeyName;
rc.ResultColumn = ci.ResultColumn;
rc.ComputedColumn = ci.ComputedColumn;
rc.ColumnType = ci.ColumnType;
rc.ColumnAlias = ci.ColumnAlias;
rc.LazyLoad = ci.LazyLoad;
rc.IsOneToMany = ci.OneToManyColumn;
rc.IsOneToOne = ci.OneToOneColumn;
try
{
if (mi.ReflectedType != null)
{
if (mi.GetMemberInfoType().IsGenericType ||
mi.GetMemberInfoType().GetGenericTypeDefinition() == typeof (IEnumerable<>))
{
rc.IsGeneric = true;
}
}
}
catch (Exception)
{
}
RelationshipColumns.Add(rc.ColumnName, rc);
}
continue;
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class RelationshipAttribute : Attribute
{
public RelationshipAttribute(string column = "Id", bool lazyLoad = false)
{
Column = column;
LazyLoad = lazyLoad;
}
public bool LazyLoad { get; set; }
public string Column { get; set; }
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class OneToOneAttribute : RelationshipAttribute
{
public OneToOneAttribute(string column = "Id", bool lazyLoad = false)
{
Column = column;
LazyLoad = lazyLoad;
}
}
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
public class OneToManyAttribute : RelationshipAttribute
{
public OneToManyAttribute(string column = "Id", bool lazyLoad = false)
{
Column = column;
LazyLoad = lazyLoad;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment