patterncsharpMinor
MergeUtility for Entity Framework
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
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
I would return directly and get rid of the Object variable.
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 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.