Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 61 additions & 31 deletions DapperExtensions/DapperImplementor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public DapperImplementor(ISqlGenerator sqlGenerator)

public T Get<T>(IDbConnection connection, dynamic id, IDbTransaction transaction, int? commandTimeout, IList<IReferenceMap> includedProperties = null) where T : class
{
return (T)InternalGet<T>(connection, id, transaction, commandTimeout, null, includedProperties);
return (T)InternalGet<T>(connection, id, transaction, commandTimeout, null, includedProperties, keyPredicate: true);
}

public TOut GetPartial<TIn, TOut>(IDbConnection connection, Expression<Func<TIn, TOut>> func, dynamic id, IDbTransaction transaction, int? commandTimeout, IList<IReferenceMap> includedProperties = null) where TIn : class where TOut : class
Expand All @@ -84,7 +84,7 @@ public void Insert<T>(IDbConnection connection, IEnumerable<T> entities, IDbTran

public dynamic Insert<T>(IDbConnection connection, T entity, IDbTransaction transaction, int? commandTimeout) where T : class
{
var classMap = SqlGenerator.Configuration.GetMap<T>();
var classMap = SqlGenerator.Configuration.GetMap(entity.GetType());
var nonIdentityKeyProperties = classMap.Properties.Where(p => p.KeyType == KeyType.Guid || p.KeyType == KeyType.Assigned).ToList();
var identityColumn = classMap.Properties.SingleOrDefault(p => p.KeyType == KeyType.Identity);
var triggerIdentityColumn = classMap.Properties.SingleOrDefault(p => p.KeyType == KeyType.TriggerIdentity);
Expand Down Expand Up @@ -337,7 +337,30 @@ protected static IPredicate GetIdPredicate(IClassMapper classMap, object id)
return ReturnPredicate(predicates);
}

protected static IPredicate GetKeyPredicate<T>(IClassMapper classMap, T entity) where T : class
protected static IPredicate GetKeyPredicate(IClassMapper classMap, object entity)
{
var whereFields = classMap.Properties.Where(p => p.KeyType != KeyType.NotAKey && p.KeyType != KeyType.ForeignKey);
if (!whereFields.Any())
{
throw new ArgumentException("At least one Key column must be defined.");
}

IList<IPredicate> predicates = new List<IPredicate>();
var predicateType = typeof(FieldPredicate<>).MakeGenericType(classMap.EntityType);
foreach (var field in whereFields)
{
var fieldPredicate = Activator.CreateInstance(predicateType) as IFieldPredicate;
fieldPredicate.Not = false;
fieldPredicate.Operator = Operator.Eq;
fieldPredicate.PropertyName = field.Name;
fieldPredicate.Value = entity;
predicates.Add(fieldPredicate);
}

return ReturnPredicate(predicates);
}

protected static IPredicate GetKeyPredicate<T>(IClassMapper classMap, T entity)
{
var whereFields = classMap.Properties.Where(p => p.KeyType != KeyType.NotAKey && p.KeyType != KeyType.ForeignKey);
if (!whereFields.Any())
Expand Down Expand Up @@ -442,17 +465,22 @@ protected void SetAutoMapperIdentifier(IList<Table> tables)
}
}

protected string GetColumnAliasFromSimpleAlias(string simpleAlias)
protected string GetColumnAliasFromSimpleAlias<T>(string simpleAlias) where T : class
{
if (SqlGenerator.AllColumns.Any(c => c.SimpleAlias.Equals(simpleAlias, StringComparison.InvariantCultureIgnoreCase)))
return SqlGenerator.AllColumns.Where(c => c.SimpleAlias.Equals(simpleAlias, StringComparison.InvariantCultureIgnoreCase)).Select(c => c.Alias).Single();
var allColumns = SqlGenerator.GetColumnsByClassMapper<T>().ToList();

if (allColumns.Any(c => c.SimpleAlias.Equals(simpleAlias, StringComparison.InvariantCultureIgnoreCase)))
return allColumns.Where(c => c.SimpleAlias.Equals(simpleAlias, StringComparison.InvariantCultureIgnoreCase)).Select(c => c.Alias).Single();
return "";
}

protected string GetSimpleAliasFromColumnAlias(string columnAlias)
protected string GetSimpleAliasFromColumnAlias(IClassMapper classMapper, string columnAlias)
{
if (SqlGenerator.AllColumns.Any(c => c.Alias.Equals(columnAlias, StringComparison.InvariantCultureIgnoreCase)))
return SqlGenerator.AllColumns.Where(c => c.Alias.Equals(columnAlias, StringComparison.InvariantCultureIgnoreCase)).Select(c => c.SimpleAlias).Single();
var allColumns = SqlGenerator.GetColumnsByClassMapper(classMapper,prefix: "p").ToList();

if (allColumns.Any(c => c.Alias.Equals(columnAlias, StringComparison.InvariantCultureIgnoreCase)))
return allColumns.Where(c => c.Alias.Equals(columnAlias, StringComparison.InvariantCultureIgnoreCase)).Select(c => c.SimpleAlias).Single();

return "";
}

Expand All @@ -464,15 +492,15 @@ protected IEnumerable<T> MappColumns<T>(IEnumerable<dynamic> values) where T : c
var dictionary = new Dictionary<string, object>();
foreach (KeyValuePair<string, object> kvp in d)
{
var alias = GetColumnAliasFromSimpleAlias(kvp.Key);
var alias = GetColumnAliasFromSimpleAlias<T>(kvp.Key);
if (!string.IsNullOrEmpty(alias))
dictionary.Add(alias, kvp.Value);
}

list.Add(dictionary);
}

SetAutoMapperIdentifier(SqlGenerator.MappedTables);
SetAutoMapperIdentifier(SqlGenerator.MappedTables.ToList());

return AutoMapper.Map<T>(list, false);
}
Expand All @@ -496,16 +524,16 @@ protected static DynamicParameters GetDynamicParameters(Dictionary<string, objec
return dynamicParameters;
}

protected virtual DynamicParameters AddParameter<T>(T entity, DynamicParameters parameters, IMemberMap prop, bool useColumnAlias = false)
protected virtual DynamicParameters AddParameter<T>(T entity, DynamicParameters parameters, IMemberMap prop, bool useColumnAlias = false) where T : class
{
var propValue = prop.GetValue(entity);
var parameter = ReflectionHelper.GetParameter(typeof(T), SqlGenerator, prop.Name, propValue);
var alias = GetSimpleAliasFromColumnAlias(parameter.Name);
var parameter = ReflectionHelper.GetParameter(entity.GetType(), SqlGenerator, prop.Name, propValue);
var alias = GetSimpleAliasFromColumnAlias(SqlGenerator.Configuration.GetMap(entity.GetType()),parameter.Name);
var name = useColumnAlias ? string.IsNullOrEmpty(alias) ? parameter.Name : alias : parameter.Name;

parameters ??= new DynamicParameters();

if (prop.MemberInfo.DeclaringType == typeof(bool) || (prop.MemberInfo.DeclaringType.IsGenericType && prop.MemberType.GetGenericTypeDefinition() == typeof(Nullable<>) && prop.MemberInfo.DeclaringType.GetGenericArguments()[0] == typeof(bool)))
if (prop.MemberInfo.DeclaringType == typeof(bool) || (prop.MemberInfo.DeclaringType.IsGenericType && prop.MemberType.IsGenericType && prop.MemberType.GetGenericTypeDefinition() == typeof(Nullable<>) && prop.MemberInfo.DeclaringType.GetGenericArguments()[0] == typeof(bool)))
{
var value = (bool?)propValue;
if (!value.HasValue)
Expand All @@ -531,7 +559,7 @@ protected virtual DynamicParameters AddParameter<T>(T entity, DynamicParameters
return parameters;
}

private DynamicParameters GetDynamicParameters<T>(T entity, IClassMapper classMap, IList<IMemberMap> sequenceColumn, IList<MemberInfo> foreignKeys, IList<MemberInfo> ignoredColumns, bool useColumnAlias)
private DynamicParameters GetDynamicParameters<T>(T entity, IClassMapper classMap, IList<IMemberMap> sequenceColumn, IList<MemberInfo> foreignKeys, IList<MemberInfo> ignoredColumns, bool useColumnAlias) where T : class
{
var keyColumns = sequenceColumn.Count == 0 ? classMap.Properties.Where(p => p.KeyType == KeyType.Assigned || p.KeyType == KeyType.Guid)?.ToList() : sequenceColumn;

Expand All @@ -545,7 +573,7 @@ private DynamicParameters GetDynamicParameters<T>(T entity, IClassMapper classMa
return dynamicParameters;
}

public DynamicParameters GetDynamicParameters<T>(IClassMapper classMap, T entity, bool useColumnAlias = false)
public DynamicParameters GetDynamicParameters<T>(IClassMapper classMap, T entity, bool useColumnAlias = false) where T : class
{
var sequenceIdentityColumn = classMap.Properties.Where(p => p.KeyType == KeyType.SequenceIdentity)?.ToList();
var foreignKeys = classMap.Properties.Where(p => p.KeyType == KeyType.ForeignKey).Select(p => p.MemberInfo).ToList();
Expand All @@ -557,7 +585,7 @@ public DynamicParameters GetDynamicParameters<T>(IClassMapper classMap, T entity
return GetDynamicParameters(entity, classMap, sequenceIdentityColumn, foreignKeys, ignored, useColumnAlias);
}

public DynamicParameters GetDynamicParameters<T>(T entity, DynamicParameters dynamicParameters, IMemberMap keyColumn, bool useColumnAlias = false)
public DynamicParameters GetDynamicParameters<T>(T entity, DynamicParameters dynamicParameters, IMemberMap keyColumn, bool useColumnAlias = false) where T : class
{
dynamicParameters ??= new DynamicParameters();
foreach (var prop in entity.GetType().GetProperties(BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.Public)
Expand Down Expand Up @@ -649,8 +677,8 @@ private object InsertIdentity(IDbConnection connection, IDbTransaction transacti
}
}

private IDictionary<string, object> AddSequenceParameter<T>(IDbConnection connection, T entity,
IMemberMap key, DynamicParameters dynamicParameters, IDictionary<string, object> keyValues)
private IDictionary<string, object> AddSequenceParameter<T>(IDbConnection connection, T entity,
IMemberMap key, DynamicParameters dynamicParameters, IDictionary<string, object> keyValues) where T : class
{
var query = $"select {key.SequenceName}.nextval seq from dual";
var value = connection.ExecuteScalar<int>(query);
Expand All @@ -665,7 +693,7 @@ private IDictionary<string, object> AddSequenceParameter<T>(IDbConnection connec
return keyValues;
}

private void AddKeyParameters<T>(T entity, IList<IMemberMap> keyList, DynamicParameters dynamicParameters, bool useColumnAlias = false)
private void AddKeyParameters<T>(T entity, IList<IMemberMap> keyList, DynamicParameters dynamicParameters, bool useColumnAlias = false) where T : class
{
foreach (var prop in keyList)
{
Expand Down Expand Up @@ -698,13 +726,9 @@ protected dynamic InternalInsert<T>(IDbConnection connection, T entity, IDbTrans
dynamicParameters = GetDynamicParameters(entity, dynamicParameters, keyColumn, true);

if (triggerIdentityColumn != null)
{
keyValue = InsertTriggered(connection, entity, transaction, commandTimeout, sql, triggerIdentityColumn, dynamicParameters);
}
keyValue = Convert.ChangeType(InsertTriggered(connection, entity, transaction, commandTimeout, sql, triggerIdentityColumn, dynamicParameters), keyColumn.MemberType);
else
{
keyValue = InsertIdentity(connection, transaction, commandTimeout, classMap, sql, dynamicParameters);
}
keyValue = Convert.ChangeType(InsertIdentity(connection, transaction, commandTimeout, classMap, sql, dynamicParameters), keyColumn.MemberType);

keyValues.Add(keyColumn.Name, keyValue);
keyColumn.SetValue(entity, keyValue);
Expand Down Expand Up @@ -768,15 +792,15 @@ protected void InternalUpdate<T>(IDbConnection connection, IEnumerable<T> entiti
InternalUpdate(connection, e, classMap, predicate, transaction, cols, commandTimeout, ignoreAllKeyProperties);
}

protected T InternalGet<T>(IDbConnection connection, dynamic id, IDbTransaction transaction, int? commandTimeout, IList<IProjection> colsToSelect, IList<IReferenceMap> includedProperties = null) where T : class
protected T InternalGet<T>(IDbConnection connection, dynamic id, IDbTransaction transaction, int? commandTimeout, IList<IProjection> colsToSelect, IList<IReferenceMap> includedProperties = null, bool keyPredicate = false) where T : class
{
var result = (IEnumerable<T>)InternalGetListAutoMap<T>(connection, id, null, transaction, commandTimeout, true, colsToSelect, includedProperties);
var result = (IEnumerable<T>)InternalGetListAutoMap<T>(connection, id, null, transaction, commandTimeout, true, colsToSelect, includedProperties, keyPredicate);
return result.SingleOrDefault();
}

protected IEnumerable<T> InternalGetListAutoMap<T>(IDbConnection connection, object predicate, IList<ISort> sort, IDbTransaction transaction, int? commandTimeout, bool buffered, IList<IProjection> colsToSelect, IList<IReferenceMap> includedProperties = null) where T : class
protected IEnumerable<T> InternalGetListAutoMap<T>(IDbConnection connection, object predicate, IList<ISort> sort, IDbTransaction transaction, int? commandTimeout, bool buffered, IList<IProjection> colsToSelect, IList<IReferenceMap> includedProperties = null, bool keyPredicate = false) where T : class
{
GetMapAndPredicate<T>(predicate, out var classMap, out var wherePredicate);
GetMapAndPredicate<T>(predicate, out var classMap, out var wherePredicate, keyPredicate);
return GetListAutoMap<T>(connection, colsToSelect, classMap, wherePredicate, sort, transaction, commandTimeout, buffered, includedProperties);
}

Expand Down Expand Up @@ -804,5 +828,11 @@ protected virtual void GetMapAndPredicate<T>(object predicateValue, out IClassMa
classMapper = SqlGenerator.Configuration.GetMap<T>();
wherePredicate = keyPredicate ? GetKeyPredicate(classMapper, predicateValue) : GetPredicate(classMapper, predicateValue);
}

protected virtual void GetMapAndPredicate<T>(T entity, out IClassMapper classMapper, out IPredicate wherePredicate, bool keyPredicate = false) where T : class
{
classMapper = SqlGenerator.Configuration.GetMap(entity.GetType());
wherePredicate = keyPredicate ? GetKeyPredicate(classMapper, entity) : GetPredicate(classMapper, entity);
}
}
}
5 changes: 5 additions & 0 deletions DapperExtensions/Mapper/Table.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ public class Table
public PropertyInfo PropertyInfo { get; set; }
public bool IsVirtual { get; set; }
public IClassMapper ClassMapper { get; set; }

public override string ToString()
{
return $"{EntityType} - {Alias}";
}
}
}

Loading