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

MergeUtility for Entity Framework

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

Problem

Here is a utility that supports ETL/merging in Entity Framework.

If it's not appealing as a general purpose tool, why?

If it is appealing as a general purpose tool, how might the design be made better?

Also, I'm not the world's most experienced programmer when it comes to writing re-usable code with paramaterized types - any feedback on that aspect would be appreciated.

```
public static class MergeUtility
{
///
/// TODO: documentation
///
/// The type of the source items.
/// The type of the destination container.
/// The type of the destination items.
/// A function returning an enumerable set of source items.
/// A function returning a destination container.
/// The name of the property on each source item who's value uniquely identifies it in the whole set.
/// The name of the property on the target container who's value is the ObjectSet containing the target items.
/// The name of the property on each target item who's value uniquely identifies it in the whole set.
/// A function called when the merge is completed to save the changes in the target container.
public static void Merge(
Func> items,
Func container,
string sourceKey,
string targetSet,
string targetKey,
Action save)
where TItem : class
where TContainer : IDisposable
where TTarget : class, new()
{
Log();

var source = items();

using (var destination = container())
{
var target = destination.MemberValue>(targetSet);

var existing = target.ToDictionary(c => c.MemberValue(targetKey));

var mapper = new Mapper();

foreach (var item in source)
{
var id = item.MemberValue(sourceKey);

TTarget entity;

if (existing.ContainsKey(id))
{
entity = existing[id];
}
else

Solution

In this object method I would change a couple of things

private object Convert(Type convertToType)
    {
        object converted = null;

        if (this.Value == null)
        {
            return converted;
        }
        else if (convertToType.IsAssignableFrom(this.type))
        {
            converted = this.Value;
        }
        else
        {
            var conversionKey = Tuple.Create(this.type, convertToType);

            if (Conversions.ContainsKey(conversionKey))
            {
                converted = Conversions[conversionKey](this.Value);
            }
            else
            {
                throw new Exception(convertToType.Name + " is not assignable from " + this.type.Name);
            }
        }

        return converted;
    }


I would return directly and get rid of the Object variable.

private object Convert(Type convertToType)
{
    if (this.Value == null)
    {
        return null;
    }
    else if (convertToType.IsAssignableFrom(this.type))
    {
        return this.Value;
    }
    else
    {
        var conversionKey = Tuple.Create(this.type, convertToType);

        if (Conversions.ContainsKey(conversionKey))
        {
            return Conversions[conversionKey](this.Value);
        }
        else
        {
            throw new Exception(convertToType.Name + " is not assignable from " + this.type.Name);
        }
    }
    return null;
}


we were discussing this question in The Second Monitor and thought that it would be a good idea to turn this method into a Generic Method like so

private T Convert(objectToConvert)
{
    if (this.Value == null)
    {
        return null;
    }
    else if (convertToType.IsAssignableFrom(this.type))
    {
        return this.Value;
    }
    else
    {
        var conversionKey = Tuple.Create(this.type, convertToType);

        if (Conversions.ContainsKey(conversionKey))
        {
            return Conversions[conversionKey](this.Value);
        }
        else
        {
            throw new Exception(convertToType.Name + " is not assignable from " + this.type.Name);
        }
    }
    return null;
}

Code Snippets

private object Convert(Type convertToType)
    {
        object converted = null;

        if (this.Value == null)
        {
            return converted;
        }
        else if (convertToType.IsAssignableFrom(this.type))
        {
            converted = this.Value;
        }
        else
        {
            var conversionKey = Tuple.Create(this.type, convertToType);

            if (Conversions.ContainsKey(conversionKey))
            {
                converted = Conversions[conversionKey](this.Value);
            }
            else
            {
                throw new Exception(convertToType.Name + " is not assignable from " + this.type.Name);
            }
        }

        return converted;
    }
private object Convert(Type convertToType)
{
    if (this.Value == null)
    {
        return null;
    }
    else if (convertToType.IsAssignableFrom(this.type))
    {
        return this.Value;
    }
    else
    {
        var conversionKey = Tuple.Create(this.type, convertToType);

        if (Conversions.ContainsKey(conversionKey))
        {
            return Conversions[conversionKey](this.Value);
        }
        else
        {
            throw new Exception(convertToType.Name + " is not assignable from " + this.type.Name);
        }
    }
    return null;
}
private T Convert<T>(objectToConvert)
{
    if (this.Value == null)
    {
        return null;
    }
    else if (convertToType.IsAssignableFrom(this.type))
    {
        return this.Value;
    }
    else
    {
        var conversionKey = Tuple.Create(this.type, convertToType);

        if (Conversions.ContainsKey(conversionKey))
        {
            return Conversions[conversionKey](this.Value);
        }
        else
        {
            throw new Exception(convertToType.Name + " is not assignable from " + this.type.Name);
        }
    }
    return null;
}

Context

StackExchange Code Review Q#11231, answer score: 2

Revisions (0)

No revisions yet.