diff --git a/Src/Asp.NetCore2/SqlSugar/Abstract/SaveableProvider/Storageable.cs b/Src/Asp.NetCore2/SqlSugar/Abstract/SaveableProvider/Storageable.cs index fe139d9d7..54844d2ff 100644 --- a/Src/Asp.NetCore2/SqlSugar/Abstract/SaveableProvider/Storageable.cs +++ b/Src/Asp.NetCore2/SqlSugar/Abstract/SaveableProvider/Storageable.cs @@ -291,6 +291,14 @@ namespace SqlSugar } } + + public IStorageable WhereColumns(string [] columns) + { + var list = columns.Select(it=>this.Context.EntityMaintenance.GetDbColumnName(it)).ToList(); + var exp=ExpressionBuilderHelper.CreateNewFields(this.Context.EntityMaintenance.GetEntityInfo(), list); + return this.WhereColumns(exp); + } + private void SetConditList(List> itemList, List whereColumns, List conditList) { ; diff --git a/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/MemberInitExpressionResolve.cs b/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/MemberInitExpressionResolve.cs index 6f52fdcdb..3677a86c3 100644 --- a/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/MemberInitExpressionResolve.cs +++ b/Src/Asp.NetCore2/SqlSugar/ExpressionsToSql/ResolveItems/MemberInitExpressionResolve.cs @@ -19,6 +19,7 @@ namespace SqlSugar break; case ResolveExpressType.WhereMultiple: break; + case ResolveExpressType.ArraySingle: case ResolveExpressType.SelectSingle: Select(expression, parameter, true); break; diff --git a/Src/Asp.NetCore2/SqlSugar/Interface/IStorageable.cs b/Src/Asp.NetCore2/SqlSugar/Interface/IStorageable.cs index cb52c65bd..b266ded9f 100644 --- a/Src/Asp.NetCore2/SqlSugar/Interface/IStorageable.cs +++ b/Src/Asp.NetCore2/SqlSugar/Interface/IStorageable.cs @@ -9,6 +9,7 @@ namespace SqlSugar public interface IStorageable where T : class, new() { IStorageable WhereColumns(Expression> columns); + IStorageable WhereColumns(string [] columns); IStorageable SplitInsert(Func, bool> conditions, string message=null); IStorageable SplitUpdate(Func, bool> conditions, string message = null); IStorageable Saveable(string inserMessage = null, string updateMessage = null); diff --git a/Src/Asp.NetCore2/SqlSugar/Utilities/ExpressionBuilderHelper.cs b/Src/Asp.NetCore2/SqlSugar/Utilities/ExpressionBuilderHelper.cs new file mode 100644 index 000000000..a096bf10b --- /dev/null +++ b/Src/Asp.NetCore2/SqlSugar/Utilities/ExpressionBuilderHelper.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace SqlSugar +{ + public class ExpressionBuilderHelper + { + public static Expression> CreateNewFields(EntityInfo entity,List propertyNames) + { + Type sourceType = typeof(T); + Dictionary sourceProperties = entity.Columns.Where(it=> propertyNames.Contains(it.PropertyName)).ToDictionary(it=>it.PropertyName,it=>it.PropertyInfo); + + Type dynamicType = LinqRuntimeTypeBuilder.GetDynamicType(sourceProperties.Values); + + ParameterExpression sourceItem = Expression.Parameter(sourceType, "t"); + IEnumerable bindings = dynamicType.GetRuntimeProperties().Select(p => Expression.Bind(p, Expression.Property(sourceItem, sourceProperties[p.Name]))).OfType(); + + return Expression.Lambda>(Expression.MemberInit( + Expression.New(dynamicType.GetConstructor(Type.EmptyTypes)), bindings), sourceItem); + } + } + internal static class LinqRuntimeTypeBuilder + { + private static readonly AssemblyName AssemblyName = new AssemblyName() { Name = "LinqRuntimeTypes4iTheoChan" }; + private static readonly ModuleBuilder ModuleBuilder; + private static readonly Dictionary BuiltTypes = new Dictionary(); + + static LinqRuntimeTypeBuilder() + { + ModuleBuilder = AssemblyBuilder.DefineDynamicAssembly(AssemblyName, AssemblyBuilderAccess.Run).DefineDynamicModule(AssemblyName.Name); + } + + private static string GetTypeKey(Dictionary properties) + { + //TODO: optimize the type caching -- if fields are simply reordered, that doesn't mean that they're actually different types, so this needs to be smarter + string key = string.Empty; + foreach (var prop in properties) + key += prop.Key + ";" + prop.Value.Name + ";"; + + return key; + } + + private const MethodAttributes RuntimeGetSetAttrs = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig; + + public static Type BuildDynamicType(Dictionary properties) + { + if (null == properties) + throw new ArgumentNullException(nameof(properties)); + if (0 == properties.Count) + throw new ArgumentOutOfRangeException(nameof(properties), "fields must have at least 1 field definition"); + + try + { + // Acquires an exclusive lock on the specified object. + Monitor.Enter(BuiltTypes); + string className = GetTypeKey(properties); + + if (BuiltTypes.ContainsKey(className)) + return BuiltTypes[className]; + + TypeBuilder typeBdr = ModuleBuilder.DefineType(className, TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Serializable); + + foreach (var prop in properties) + { + var propertyBdr = typeBdr.DefineProperty(name: prop.Key, attributes: PropertyAttributes.None, returnType: prop.Value, parameterTypes: null); + var fieldBdr = typeBdr.DefineField("itheofield_" + prop.Key, prop.Value, FieldAttributes.Private); + + MethodBuilder getMethodBdr = typeBdr.DefineMethod("get_" + prop.Key, RuntimeGetSetAttrs, prop.Value, Type.EmptyTypes); + ILGenerator getIL = getMethodBdr.GetILGenerator(); + getIL.Emit(OpCodes.Ldarg_0); + getIL.Emit(OpCodes.Ldfld, fieldBdr); + getIL.Emit(OpCodes.Ret); + + MethodBuilder setMethodBdr = typeBdr.DefineMethod("set_" + prop.Key, RuntimeGetSetAttrs, null, new Type[] { prop.Value }); + ILGenerator setIL = setMethodBdr.GetILGenerator(); + setIL.Emit(OpCodes.Ldarg_0); + setIL.Emit(OpCodes.Ldarg_1); + setIL.Emit(OpCodes.Stfld, fieldBdr); + setIL.Emit(OpCodes.Ret); + + propertyBdr.SetGetMethod(getMethodBdr); + propertyBdr.SetSetMethod(setMethodBdr); + } + + BuiltTypes[className] = typeBdr.CreateType(); + + return BuiltTypes[className]; + } + catch + { + throw; + } + finally + { + Monitor.Exit(BuiltTypes); + } + } + + private static string GetTypeKey(IEnumerable properties) + { + return GetTypeKey(properties.ToDictionary(f => f.Name, f => f.PropertyType)); + } + + public static Type GetDynamicType(IEnumerable properties) + { + return BuildDynamicType(properties.ToDictionary(f => f.Name, f => f.PropertyType)); + } + } +} \ No newline at end of file