mirror of
https://github.com/DapperLib/Dapper.git
synced 2026-10-17 05:12:13 +08:00
Merge branch 'master' of https://github.com/StackExchange/Dapper
This commit is contained in:
+40
-18
@@ -30,6 +30,10 @@ namespace Dapper
|
||||
/// </summary>
|
||||
public static partial class SqlMapper
|
||||
{
|
||||
private class PropertyInfoByNameComparer : IComparer<PropertyInfo>
|
||||
{
|
||||
public int Compare(PropertyInfo x, PropertyInfo y) => string.CompareOrdinal(x.Name, y.Name);
|
||||
}
|
||||
private static int GetColumnHash(IDataReader reader, int startBound = 0, int length = -1)
|
||||
{
|
||||
unchecked
|
||||
@@ -2217,7 +2221,13 @@ namespace Dapper
|
||||
|
||||
private static IEnumerable<PropertyInfo> FilterParameters(IEnumerable<PropertyInfo> parameters, string sql)
|
||||
{
|
||||
return parameters.Where(p => Regex.IsMatch(sql, "[?@:]" + p.Name + @"([^\p{L}\p{N}_]+|$)", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.CultureInvariant));
|
||||
var list = new List<PropertyInfo>(16);
|
||||
foreach (var p in parameters)
|
||||
{
|
||||
if (Regex.IsMatch(sql, @"[?@:]" + p.Name + @"([^\p{L}\p{N}_]+|$)", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.CultureInvariant))
|
||||
list.Add(p);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
// look for ? / @ / : *by itself*
|
||||
@@ -2356,7 +2366,7 @@ namespace Dapper
|
||||
public static Action<IDbCommand, object> CreateParamInfoGenerator(Identity identity, bool checkForDuplicates, bool removeUnused) =>
|
||||
CreateParamInfoGenerator(identity, checkForDuplicates, removeUnused, GetLiteralTokens(identity.sql));
|
||||
|
||||
private static bool IsValueTuple(Type type) => type?.IsValueType() == true && type.FullName.StartsWith("System.ValueTuple`");
|
||||
private static bool IsValueTuple(Type type) => type?.IsValueType() == true && type.FullName.StartsWith("System.ValueTuple`", StringComparison.Ordinal);
|
||||
|
||||
private static List<IMemberMap> GetValueTupleMembers(Type type, string[] names)
|
||||
{
|
||||
@@ -2415,19 +2425,27 @@ namespace Dapper
|
||||
il.Emit(OpCodes.Ldarg_0); // stack is now [command]
|
||||
il.EmitCall(OpCodes.Callvirt, typeof(IDbCommand).GetProperty(nameof(IDbCommand.Parameters)).GetGetMethod(), null); // stack is now [parameters]
|
||||
|
||||
var propsArr = type.GetProperties().Where(p => p.GetIndexParameters().Length == 0).ToArray();
|
||||
var allTypeProps = type.GetProperties();
|
||||
var propsList = new List<PropertyInfo>(allTypeProps.Length);
|
||||
for(int i = 0; i < allTypeProps.Length; ++i)
|
||||
{
|
||||
var p = allTypeProps[i];
|
||||
if (p.GetIndexParameters().Length == 0)
|
||||
propsList.Add(p);
|
||||
}
|
||||
|
||||
var ctors = type.GetConstructors();
|
||||
ParameterInfo[] ctorParams;
|
||||
IEnumerable<PropertyInfo> props = null;
|
||||
// try to detect tuple patterns, e.g. anon-types, and use that to choose the order
|
||||
// otherwise: alphabetical
|
||||
if (ctors.Length == 1 && propsArr.Length == (ctorParams = ctors[0].GetParameters()).Length)
|
||||
if (ctors.Length == 1 && propsList.Count == (ctorParams = ctors[0].GetParameters()).Length)
|
||||
{
|
||||
// check if reflection was kind enough to put everything in the right order for us
|
||||
bool ok = true;
|
||||
for (int i = 0; i < propsArr.Length; i++)
|
||||
for (int i = 0; i < propsList.Count; i++)
|
||||
{
|
||||
if (!string.Equals(propsArr[i].Name, ctorParams[i].Name, StringComparison.OrdinalIgnoreCase))
|
||||
if (!string.Equals(propsList[i].Name, ctorParams[i].Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
ok = false;
|
||||
break;
|
||||
@@ -2436,7 +2454,7 @@ namespace Dapper
|
||||
if(ok)
|
||||
{
|
||||
// pre-sorted; the reflection gods have smiled upon us
|
||||
props = propsArr;
|
||||
props = propsList;
|
||||
}
|
||||
else { // might still all be accounted for; check the hard way
|
||||
var positionByName = new Dictionary<string,int>(StringComparer.OrdinalIgnoreCase);
|
||||
@@ -2444,13 +2462,13 @@ namespace Dapper
|
||||
{
|
||||
positionByName[param.Name] = param.Position;
|
||||
}
|
||||
if (positionByName.Count == propsArr.Length)
|
||||
if (positionByName.Count == propsList.Count)
|
||||
{
|
||||
int[] positions = new int[propsArr.Length];
|
||||
int[] positions = new int[propsList.Count];
|
||||
ok = true;
|
||||
for (int i = 0; i < propsArr.Length; i++)
|
||||
for (int i = 0; i < propsList.Count; i++)
|
||||
{
|
||||
if (!positionByName.TryGetValue(propsArr[i].Name, out int pos))
|
||||
if (!positionByName.TryGetValue(propsList[i].Name, out int pos))
|
||||
{
|
||||
ok = false;
|
||||
break;
|
||||
@@ -2459,13 +2477,17 @@ namespace Dapper
|
||||
}
|
||||
if (ok)
|
||||
{
|
||||
Array.Sort(positions, propsArr);
|
||||
props = propsArr;
|
||||
props = propsList.ToArray();
|
||||
Array.Sort(positions, (PropertyInfo[]) props);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
props = props ?? propsArr.OrderBy(x => x.Name);
|
||||
if(props == null)
|
||||
{
|
||||
propsList.Sort(new PropertyInfoByNameComparer());
|
||||
props = propsList;
|
||||
}
|
||||
if (filterParams)
|
||||
{
|
||||
props = FilterParameters(props, identity.sql);
|
||||
@@ -2677,7 +2699,7 @@ namespace Dapper
|
||||
// stack is currently [parameters]
|
||||
il.Emit(OpCodes.Pop); // stack is now empty
|
||||
|
||||
if(literals.Count != 0 && propsArr != null)
|
||||
if(literals.Count != 0 && propsList != null)
|
||||
{
|
||||
il.Emit(OpCodes.Ldarg_0); // command
|
||||
il.Emit(OpCodes.Ldarg_0); // command, command
|
||||
@@ -2690,12 +2712,12 @@ namespace Dapper
|
||||
// find the best member, preferring case-sensitive
|
||||
PropertyInfo exact = null, fallback = null;
|
||||
string huntName = literal.Member;
|
||||
for(int i = 0; i < propsArr.Length;i++)
|
||||
for(int i = 0; i < propsList.Count; i++)
|
||||
{
|
||||
string thisName = propsArr[i].Name;
|
||||
string thisName = propsList[i].Name;
|
||||
if(string.Equals(thisName, huntName, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
fallback = propsArr[i];
|
||||
fallback = propsList[i];
|
||||
if(string.Equals(thisName, huntName, StringComparison.Ordinal))
|
||||
{
|
||||
exact = fallback;
|
||||
|
||||
Reference in New Issue
Block a user