HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Exporting site and address data

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
addressexportingsiteanddata

Problem

These two methods do very similar things. Is it possible to condense these somehow? This is using the Entity Framework.

public void ExportSiteData (FLEX_INV_EXP_SITE siteData)
{
    var uniqueSite = from e in _context.FLEX_INV_EXP_SITE
                     where e.SITE_ID == siteData.SITE_ID
                     select e;
    var count = uniqueSite.Count();

    if (count != 0) return;
    _context.FLEX_INV_EXP_SITE.AddObject(siteData);
    _context.SaveChanges();
}

public void ExportAddressData (FLEX_INV_EXP_ADDRESS addressData)
{
    var uniqueSite = from e in _context.FLEX_INV_EXP_ADDRESS
                     where e.SITE_ID == addressData.SITE_ID
                     select e;
    var count = uniqueSite.Count();

    if (count != 0) return;
    _context.FLEX_INV_EXP_ADDRESS.AddObject(addressData);
    _context.SaveChanges();
}

Solution

It seems the only two unique things about the blocks of code are the Tables that you are searching/adding to and how the SITE_IDs are obtained (from different types). You could just make your method accept two additional parameters, the table that is being searched and a lambda which selects the SITE_ID. You'll just have to rewrite some expressions.

public static void ExportData(
    ObjectSet table,
    Expression> siteIdSelector,
    TEntity data)
    where TEntity : class
{
    var condition = GetCondition(siteIdSelector, data);
    var isInTable = table.Where(condition).Any();
    if (!isInTable)
    {
        table.AddObject(data);
        table.Context.SaveChanges();
    }
}

private static Expression> GetCondition(
    Expression> keySelector,
    TEntity data)
    where TEntity : class
{
    var entity = Expression.Parameter(typeof(TEntity), "entity");
    var entityKey = BindParameter(keySelector, entity);
    var dataKey = BindParameter(keySelector, Expression.Constant(data));
    var body = Expression.Equal(entityKey , dataKey);
    return Expression.Lambda>(body, entity);
}

private static Expression BindParameter(
    Expression> keySelector,
    Expression entity)
    where TEntity : class
{
    return new SubstitutionVisitor
    {
        OldExpr = keySelector.Parameters.Single(),
        NewExpr = entity,
    }.Visit(keySelector.Body);
}

public class SubstitutionVisitor : ExpressionVisitor
{
    public Expression OldExpr { get; set; }
    public Expression NewExpr { get; set; }

    public override Expression Visit(Expression node)
    {
        return (node == OldExpr) ? NewExpr : base.Visit(node);
    }
}


Then to use it, you could do something like this:

ExportData(_context.FLEX_INV_EXP_SITE, entity => entity.SITE_ID, siteData);
ExportData(_context.FLEX_INV_EXP_ADDRESS, entity => entity.SITE_ID, addressData);

Code Snippets

public static void ExportData<TEntity, TSite>(
    ObjectSet<TEntity> table,
    Expression<Func<TEntity, TSite>> siteIdSelector,
    TEntity data)
    where TEntity : class
{
    var condition = GetCondition(siteIdSelector, data);
    var isInTable = table.Where(condition).Any();
    if (!isInTable)
    {
        table.AddObject(data);
        table.Context.SaveChanges();
    }
}

private static Expression<Func<TEntity, bool>> GetCondition<TEntity, TKey>(
    Expression<Func<TEntity, TKey>> keySelector,
    TEntity data)
    where TEntity : class
{
    var entity = Expression.Parameter(typeof(TEntity), "entity");
    var entityKey = BindParameter(keySelector, entity);
    var dataKey = BindParameter(keySelector, Expression.Constant(data));
    var body = Expression.Equal(entityKey , dataKey);
    return Expression.Lambda<Func<TEntity, bool>>(body, entity);
}

private static Expression BindParameter<TEntity, TKey>(
    Expression<Func<TEntity, TKey>> keySelector,
    Expression entity)
    where TEntity : class
{
    return new SubstitutionVisitor
    {
        OldExpr = keySelector.Parameters.Single(),
        NewExpr = entity,
    }.Visit(keySelector.Body);
}

public class SubstitutionVisitor : ExpressionVisitor
{
    public Expression OldExpr { get; set; }
    public Expression NewExpr { get; set; }

    public override Expression Visit(Expression node)
    {
        return (node == OldExpr) ? NewExpr : base.Visit(node);
    }
}
ExportData(_context.FLEX_INV_EXP_SITE, entity => entity.SITE_ID, siteData);
ExportData(_context.FLEX_INV_EXP_ADDRESS, entity => entity.SITE_ID, addressData);

Context

StackExchange Code Review Q#7488, answer score: 2

Revisions (0)

No revisions yet.