diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml index d9f91124..dc0203b8 100644 --- a/FreeSql.DbContext/FreeSql.DbContext.xml +++ b/FreeSql.DbContext/FreeSql.DbContext.xml @@ -110,13 +110,6 @@ 清空状态数据 - - - 根据 lambda 条件删除数据 - - - - 添加 diff --git a/FreeSql.Tests/FreeSql.Tests/UnitTest2.cs b/FreeSql.Tests/FreeSql.Tests/UnitTest2.cs index 22d54a76..758c9ecb 100644 --- a/FreeSql.Tests/FreeSql.Tests/UnitTest2.cs +++ b/FreeSql.Tests/FreeSql.Tests/UnitTest2.cs @@ -219,6 +219,12 @@ namespace FreeSql.Tests [Fact] public void Test02() { + var start = DateTime.Now.Date; + var end = DateTime.Now.AddDays(1).Date.AddMilliseconds(-1); + var textbetween = g.sqlite.Select() + .Where(a => a.ct1.Between(start, end)) + .ToList(); + g.mysql.GlobalFilter.Apply("gft1", a => a.rowstate > -1) .Apply("gft2", a => a.rowstate > -2) .Apply("gft3", a => a.rowstate > -3); diff --git a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs index 29b0c08f..97ed7c97 100644 --- a/FreeSql/Extensions/FreeSqlGlobalExtensions.cs +++ b/FreeSql/Extensions/FreeSqlGlobalExtensions.cs @@ -1,4 +1,5 @@ using FreeSql; +using FreeSql.DataAnnotations; using System; using System.Collections; using System.Collections.Concurrent; @@ -9,6 +10,7 @@ using System.Drawing; using System.Linq; using System.Linq.Expressions; using System.Reflection; +using System.Threading; public static partial class FreeSqlGlobalExtensions { @@ -102,10 +104,7 @@ public static partial class FreeSqlGlobalExtensions var desc = item.GetType().GetField(name)?.GetCustomAttributes(typeof(DescriptionAttribute), false)?.FirstOrDefault() as DescriptionAttribute; return desc?.Description ?? name; } - public static long ToInt64(this Enum item) - { - return Convert.ToInt64(item); - } + public static long ToInt64(this Enum item) => Convert.ToInt64(item); public static IEnumerable ToSet(this long value) { var ret = new List(); @@ -222,4 +221,45 @@ public static partial class FreeSqlGlobalExtensions } #endif #endregion + + #region LambdaExpression + + public static ThreadLocal expContext = new ThreadLocal(); + + /// + /// C#: that >= between && that <= and + /// SQL: that BETWEEN between AND and + /// + /// + /// + /// + /// + [ExpressionCall] + public static bool Between(this DateTime that, DateTime between, DateTime and) + { + if (expContext.IsValueCreated == false || expContext.Value == null || expContext.Value.ParsedContent == null) + return that >= between && that <= and; + expContext.Value.Result = $"{expContext.Value.ParsedContent["that"]} between {expContext.Value.ParsedContent["start"]} and {expContext.Value.ParsedContent["end"]}"; + return false; + } + + /// + /// 注意:这个方法和 Between 有细微区别 + /// C#: that >= start && that < end + /// SQL: that >= start and that < end + /// + /// + /// + /// + /// + [ExpressionCall] + public static bool BetweenEnd(this DateTime that, DateTime start, DateTime end) + { + if (expContext.IsValueCreated == false || expContext.Value == null || expContext.Value.ParsedContent == null) + return that >= start && that < end; + expContext.Value.Result = $"{expContext.Value.ParsedContent["that"]} >= {expContext.Value.ParsedContent["start"]} and {expContext.Value.ParsedContent["that"]} < {expContext.Value.ParsedContent["end"]}"; + return false; + } + + #endregion } \ No newline at end of file diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs index b4324998..23156372 100644 --- a/FreeSql/Internal/CommonExpression.cs +++ b/FreeSql/Internal/CommonExpression.cs @@ -25,20 +25,20 @@ namespace FreeSql.Internal _common = common; } - public bool ReadAnonymousField(List _tables, StringBuilder field, ReadAnonymousTypeInfo parent, ref int index, Expression exp, Func getSelectGroupingMapString, List whereCascadeExpression) + public bool ReadAnonymousField(List _tables, StringBuilder field, ReadAnonymousTypeInfo parent, ref int index, Expression exp, Func getSelectGroupingMapString, List whereCascadeExpression, bool isAllDtoMap) { Func getTSC = () => new ExpTSC { _tables = _tables, getSelectGroupingMapString = getSelectGroupingMapString, tbtype = SelectTableInfoType.From, isQuoteName = true, isDisableDiyParse = false, style = ExpressionStyle.Where, whereCascadeExpression = whereCascadeExpression }; switch (exp.NodeType) { - case ExpressionType.Quote: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, getSelectGroupingMapString, whereCascadeExpression); - case ExpressionType.Lambda: return ReadAnonymousField(_tables, field, parent, ref index, (exp as LambdaExpression)?.Body, getSelectGroupingMapString, whereCascadeExpression); + case ExpressionType.Quote: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, getSelectGroupingMapString, whereCascadeExpression, isAllDtoMap); + case ExpressionType.Lambda: return ReadAnonymousField(_tables, field, parent, ref index, (exp as LambdaExpression)?.Body, getSelectGroupingMapString, whereCascadeExpression, isAllDtoMap); case ExpressionType.Negate: case ExpressionType.NegateChecked: parent.DbField = $"-({ExpressionLambdaToSql(exp, getTSC())})"; field.Append(", ").Append(parent.DbField); if (index >= 0) field.Append(" as").Append(++index); return false; - case ExpressionType.Convert: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, getSelectGroupingMapString, whereCascadeExpression); + case ExpressionType.Convert: return ReadAnonymousField(_tables, field, parent, ref index, (exp as UnaryExpression)?.Operand, getSelectGroupingMapString, whereCascadeExpression, isAllDtoMap); case ExpressionType.Constant: var constExp = exp as ConstantExpression; //处理自定义SQL语句,如: ToList(new { @@ -110,7 +110,7 @@ namespace FreeSql.Internal parent.Consturctor = initExp.NewExpression.Type.GetConstructors()[0]; parent.ConsturctorType = ReadAnonymousTypeInfoConsturctorType.Properties; - if (_tables != null && _tables.Any() && initExp.NewExpression.Type != _tables.FirstOrDefault().Table.Type) + if (isAllDtoMap && _tables != null && _tables.Any() && initExp.NewExpression.Type != _tables.FirstOrDefault().Table.Type) { //dto 映射 var dtoProps = initExp.NewExpression.Type.GetPropertiesDictIgnoreCase().Values; @@ -129,7 +129,7 @@ namespace FreeSql.Internal }; parent.Childs.Add(child); if (dtTb.Parameter != null) - ReadAnonymousField(_tables, field, child, ref index, Expression.Property(dtTb.Parameter, dtTb.Table.Properties[trydtocol.CsName]), getSelectGroupingMapString, whereCascadeExpression); + ReadAnonymousField(_tables, field, child, ref index, Expression.Property(dtTb.Parameter, dtTb.Table.Properties[trydtocol.CsName]), getSelectGroupingMapString, whereCascadeExpression, isAllDtoMap); else { child.DbField = $"{dtTb.Alias}.{_common.QuoteSqlName(trydtocol.Attribute.Name)}"; @@ -156,7 +156,7 @@ namespace FreeSql.Internal MapType = initAssignExp.Expression.Type }; parent.Childs.Add(child); - ReadAnonymousField(_tables, field, child, ref index, initAssignExp.Expression, getSelectGroupingMapString, whereCascadeExpression); + ReadAnonymousField(_tables, field, child, ref index, initAssignExp.Expression, getSelectGroupingMapString, whereCascadeExpression, false); } } if (parent.Childs.Any() == false) throw new Exception($"映射异常:{initExp.NewExpression.Type.Name} 没有一个属性名相同"); @@ -177,7 +177,7 @@ namespace FreeSql.Internal MapType = newExp.Arguments[a].Type }; parent.Childs.Add(child); - ReadAnonymousField(_tables, field, child, ref index, newExp.Arguments[a], getSelectGroupingMapString, whereCascadeExpression); + ReadAnonymousField(_tables, field, child, ref index, newExp.Arguments[a], getSelectGroupingMapString, whereCascadeExpression, false); } } else @@ -200,7 +200,7 @@ namespace FreeSql.Internal }; parent.Childs.Add(child); if (dtTb.Parameter != null) - ReadAnonymousField(_tables, field, child, ref index, Expression.Property(dtTb.Parameter, dtTb.Table.Properties[trydtocol.CsName]), getSelectGroupingMapString, whereCascadeExpression); + ReadAnonymousField(_tables, field, child, ref index, Expression.Property(dtTb.Parameter, dtTb.Table.Properties[trydtocol.CsName]), getSelectGroupingMapString, whereCascadeExpression, isAllDtoMap); else { child.DbField = $"{dtTb.Alias}.{_common.QuoteSqlName(trydtocol.Attribute.Name)}"; diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs index 0c7aa3c2..31cc450d 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs @@ -530,7 +530,7 @@ namespace FreeSql.Internal.CommonProvider var field = new StringBuilder(); var index = 0; - _commonExpression.ReadAnonymousField(_tables, field, map, ref index, newexp, null, _whereCascadeExpression); + _commonExpression.ReadAnonymousField(_tables, field, map, ref index, newexp, null, _whereCascadeExpression, true); return (map, field.Length > 0 ? field.Remove(0, 2).ToString() : null); } static ConcurrentDictionary _dicConstructor = new ConcurrentDictionary(); @@ -1003,7 +1003,7 @@ namespace FreeSql.Internal.CommonProvider var field = new StringBuilder(); var index = -10000; //临时规则,不返回 as1 - _commonExpression.ReadAnonymousField(_tables, field, map, ref index, columns, null, _whereCascadeExpression); + _commonExpression.ReadAnonymousField(_tables, field, map, ref index, columns, null, _whereCascadeExpression, true); this.GroupBy(field.Length > 0 ? field.Remove(0, 2).ToString() : null); return new SelectGroupingProvider(this, map, _commonExpression, _tables); } @@ -1061,7 +1061,7 @@ namespace FreeSql.Internal.CommonProvider var field = new StringBuilder(); var index = 0; - _commonExpression.ReadAnonymousField(_tables, field, map, ref index, select, null, _whereCascadeExpression); + _commonExpression.ReadAnonymousField(_tables, field, map, ref index, select, null, _whereCascadeExpression, true); return this.ToListMapReader((map, field.Length > 0 ? field.Remove(0, 2).ToString() : null)).FirstOrDefault(); } @@ -1291,7 +1291,7 @@ namespace FreeSql.Internal.CommonProvider var field = new StringBuilder(); var index = 0; - _commonExpression.ReadAnonymousField(_tables, field, map, ref index, select, null, _whereCascadeExpression); + _commonExpression.ReadAnonymousField(_tables, field, map, ref index, select, null, _whereCascadeExpression, true); return (await this.ToListMapReaderAsync((map, field.Length > 0 ? field.Remove(0, 2).ToString() : null))).FirstOrDefault(); } #endif diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs index 0e402bd1..78ac4bcc 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/SelectGroupingProvider.cs @@ -112,7 +112,7 @@ namespace FreeSql.Internal.CommonProvider var field = new StringBuilder(); var index = 0; - _comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString, null); + _comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString, null, true); var method = _select.GetType().GetMethod("ToListMapReader", BindingFlags.Instance | BindingFlags.NonPublic); method = method.MakeGenericMethod(typeof(TReturn)); return method.Invoke(_select, new object[] { (map, field.Length > 0 ? field.Remove(0, 2).ToString() : null) }) as List; @@ -126,7 +126,7 @@ namespace FreeSql.Internal.CommonProvider var field = new StringBuilder(); var index = 0; - _comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString, null); + _comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString, null, true); var method = _select.GetType().GetMethod("ToSql", new[] { typeof(string) }); return method.Invoke(_select, new object[] { field.Length > 0 ? field.Remove(0, 2).ToString() : null }) as string; } @@ -170,7 +170,7 @@ namespace FreeSql.Internal.CommonProvider var field = new StringBuilder(); var index = 0; - _comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString, null); + _comonExp.ReadAnonymousField(null, field, map, ref index, select, getSelectGroupingMapString, null, true); var method = _select.GetType().GetMethod("ToListMapReaderAsync", BindingFlags.Instance | BindingFlags.NonPublic); method = method.MakeGenericMethod(typeof(TReturn)); return method.Invoke(_select, new object[] { (map, field.Length > 0 ? field.Remove(0, 2).ToString() : null) }) as Task>;