diff --git a/FreeSql.DbContext/FreeSql.DbContext.xml b/FreeSql.DbContext/FreeSql.DbContext.xml
index ca7c357b..2735cefb 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/UnitTest3.cs b/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs
index 49ecb36e..dc3ae2e0 100644
--- a/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs
+++ b/FreeSql.Tests/FreeSql.Tests/UnitTest3.cs
@@ -116,9 +116,39 @@ namespace FreeSql.Tests
public string Name { get; set; }
}
+ [Table(Name = "EDI")]
+ public class Edi
+ {
+ [Column(Name = "EDI_ID")] public long Id { get; set; }
+ }
+ [Table(Name = "EDI_ITEM")]
+ public class EdiItem
+ {
+ [Column(Name = "EDII_ID")] public long Id { get; set; }
+ [Column(Name = "EDII_EDI_ID")] public long EdiId { get; set; }
+ }
+
[Fact]
public void Test03()
{
+ var lksdjkg1 = g.sqlite.Select()
+ .AsQueryable().Where(a => a.Id > 0).ToList();
+
+ var lksdjkg2 = g.sqlite.Select()
+ .AsQueryable().Where(a => a.Id > 0).First();
+
+ var lksdjkg3 = g.sqlite.Select()
+ .AsQueryable().Where(a => a.Id > 0).FirstOrDefault();
+
+
+ var sql222efe = g.sqlite.Select()
+ .InnerJoin((a, b) => b.Id == g.sqlite.Select().As("c").Where(c => c.EdiId == a.Id).OrderBy(c => c.Id).ToOne(c => c.Id))
+ .ToSql((a, b) => new
+ {
+ Id = a.Id,
+ EdiId = b.Id
+ });
+
var subSyetemId = "xxx";
var list = g.sqlite.Select
+
+
+ 将 ISelect<T1> 转换为 IQueryable<T1>
+ 此方法主要用于扩展,比如:abp IRepository GetAll() 接口方法需要返回 IQueryable 对象
+ 注意:IQueryable 方法污染较为严重,请尽量避免此转换
+
+
+
查询条件,Where(a => a.Id > 10),支持导航对象查询,Where(a => a.Author.Email == "2881099@qq.com")
diff --git a/FreeSql/Interface/Curd/ISelect/ISelect1.cs b/FreeSql/Interface/Curd/ISelect/ISelect1.cs
index 34c9ce6d..a6bb4622 100644
--- a/FreeSql/Interface/Curd/ISelect/ISelect1.cs
+++ b/FreeSql/Interface/Curd/ISelect/ISelect1.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Data;
+using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
@@ -377,5 +378,13 @@ namespace FreeSql
/// SQL语句
///
ISelect WithSql(string sql);
+
+ ///
+ /// 将 ISelect<T1> 转换为 IQueryable<T1>
+ /// 此方法主要用于扩展,比如:abp IRepository GetAll() 接口方法需要返回 IQueryable 对象
+ /// 注意:IQueryable 方法污染较为严重,请尽量避免此转换
+ ///
+ ///
+ IQueryable AsQueryable();
}
}
\ No newline at end of file
diff --git a/FreeSql/Internal/CommonExpression.cs b/FreeSql/Internal/CommonExpression.cs
index f9e424d1..2138f213 100644
--- a/FreeSql/Internal/CommonExpression.cs
+++ b/FreeSql/Internal/CommonExpression.cs
@@ -707,6 +707,7 @@ namespace FreeSql.Internal
case "Max":
case "Avg":
case "ToList": //where in
+ case "ToOne":
case "First":
var anyArgs = exp3.Arguments;
var exp3Stack = new Stack();
@@ -991,6 +992,7 @@ namespace FreeSql.Internal
return $"({sqlSum.Replace("\r\n", "\r\n\t")})";
break;
case "ToList":
+ case "ToOne":
case "First":
var tscClone2 = tsc.CloneDisableDiyParse();
tscClone2.isDisableDiyParse = false;
diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/QueryableProvider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/QueryableProvider.cs
new file mode 100644
index 00000000..bf52e097
--- /dev/null
+++ b/FreeSql/Internal/CommonProvider/SelectProvider/QueryableProvider.cs
@@ -0,0 +1,107 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+using System.Text;
+
+namespace FreeSql.Internal.CommonProvider
+{
+ class QueryableProvider : IQueryable
+ {
+ private Expression _expression;
+ private IQueryProvider _provider;
+ private object _select;
+ private CommonExpression _commonExpression;
+
+ public QueryableProvider(object select)
+ {
+ _select = select;
+ _commonExpression = _select.GetType().GetField("_commonExpression", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(_select) as CommonExpression;
+ _expression = Expression.Constant(this);
+ _provider = new QueryProvider(_select, _commonExpression);
+ }
+ public QueryableProvider(Expression expression, IQueryProvider provider, object select, CommonExpression commonExpression)
+ {
+ _select = select;
+ _commonExpression = commonExpression;
+ _expression = expression;
+ _provider = provider;
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ var result = _provider.Execute>(_expression);
+ if (result == null)
+ yield break;
+ foreach (var item in result)
+ {
+ yield return item;
+ }
+ }
+ IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException();
+
+ public Type ElementType => typeof(QueryableProvider);
+ public Expression Expression => _expression;
+ public IQueryProvider Provider => _provider;
+ }
+
+ class QueryProvider : IQueryProvider
+ {
+ private object _select;
+ private CommonExpression _commonExpression;
+
+ public QueryProvider(object select, CommonExpression commonExpression)
+ {
+ _select = select;
+ _commonExpression = commonExpression;
+ }
+
+ public IQueryable CreateQuery(Expression expression)
+ {
+ IQueryable query = new QueryableProvider(expression, this, _select, _commonExpression);
+ return query;
+ }
+ public IQueryable CreateQuery(Expression expression) => throw new NotImplementedException();
+
+
+ public TResult Execute(Expression expression)
+ {
+ var methodExp = expression as MethodCallExpression;
+ while (methodExp != null)
+ {
+ switch (methodExp.Method.Name)
+ {
+ case "First":
+ case "FirstOrDefault":
+ _select.GetType().GetMethod("Limit", new[] { typeof(int) }).Invoke(_select, new object[] { 1 });
+ break;
+ default:
+ var selectMethod = _select.GetType().GetMethod(methodExp.Method.Name, methodExp.Arguments.Where((a, b) => b > 0).Select(a => a.Type).ToArray());
+ if (selectMethod == null) throw new Exception($"无法找到 ISelect.{methodExp.Method.Name}({string.Join(", ", methodExp.Arguments.Select(a => a.Type.FullName))}) 方法");
+
+ var selectArgs = methodExp.Arguments.Where((a, b) => b > 0).Select(a =>
+ {
+ switch (a.NodeType)
+ {
+ case ExpressionType.Lambda: return (object)a;
+ default: return Expression.Lambda(a).Compile().DynamicInvoke();
+ }
+ }).ToArray();
+ selectMethod.Invoke(_select, selectArgs);
+ break;
+ }
+ methodExp = methodExp.Arguments.FirstOrDefault() as MethodCallExpression;
+ }
+ var resultType = typeof(TResult);
+ var resultTypeIsList = typeof(IList).IsAssignableFrom(resultType);
+ if (resultTypeIsList) resultType = resultType.GetGenericArguments()[0];
+ var ret = _select.GetType().GetMethod(resultTypeIsList ? "ToList" : "First", new Type[0])
+ .MakeGenericMethod(resultType)
+ .Invoke(_select, new object[0]);
+ return (TResult)ret;
+ }
+ public object Execute(Expression expression) => throw new NotImplementedException();
+ }
+}
diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs
index 83cb8b3d..2d3b877f 100644
--- a/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs
+++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select1Provider.cs
@@ -1071,6 +1071,8 @@ namespace FreeSql.Internal.CommonProvider
_trackToList?.Invoke(list);
}
+ public IQueryable AsQueryable() => new QueryableProvider(this);
+
#if net40
#else
async internal Task SetListAsync(IEnumerable list)