- 增加 IEnumerable<TEntity> 扩展方法 AsSelect

This commit is contained in:
28810 2019-03-15 15:03:08 +08:00
parent fccc3fc8b9
commit 23d5d33bdd
8 changed files with 139 additions and 8 deletions

View File

@ -196,6 +196,22 @@ namespace FreeSql.Tests.MySql {
var count = select.Where(a => 1 == 1).Count(); var count = select.Where(a => 1 == 1).Count();
Assert.False(select.Where(a => 1 == 2).Any()); Assert.False(select.Where(a => 1 == 2).Any());
Assert.Equal(count > 0, select.Where(a => 1 == 1).Any()); Assert.Equal(count > 0, select.Where(a => 1 == 1).Any());
var sql2222 = select.Where(a =>
select.Where(b => b.Id == a.Id &&
select.Where(c => c.Id == b.Id).Where(d => d.Id == a.Id).Where(e => e.Id == b.Id)
.Offset(a.Id)
.Any()
).Any(c => c.Id == a.Id + 10)
);
var sql2222Tolist = sql2222.ToList();
var collectionSelect = select.Where(a =>
a.Type.Guid == a.TestTypeInfoGuid &&
a.Type.Parent.Id == a.Type.ParentId &&
a.Type.Parent.Types.AsSelect().Where(b => b.Name == a.Title).Any(b => b.ParentId == a.Type.Parent.Id)
);
collectionSelect.ToList();
} }
[Fact] [Fact]
public void Count() { public void Count() {

View File

@ -70,6 +70,22 @@ namespace FreeSql.Tests.Oracle {
var count = select.Where(a => 1 == 1).Count(); var count = select.Where(a => 1 == 1).Count();
Assert.False(select.Where(a => 1 == 2).Any()); Assert.False(select.Where(a => 1 == 2).Any());
Assert.Equal(count > 0, select.Where(a => 1 == 1).Any()); Assert.Equal(count > 0, select.Where(a => 1 == 1).Any());
var sql2222 = select.Where(a =>
select.Where(b => b.Id == a.Id &&
select.Where(c => c.Id == b.Id).Where(d => d.Id == a.Id).Where(e => e.Id == b.Id)
.Offset(a.Id)
.Any()
).Any(c => c.Id == a.Id + 10)
);
var sql2222Tolist = sql2222.ToList();
var collectionSelect = select.Where(a =>
a.Type.Guid == a.TestTypeInfoGuid &&
a.Type.Parent.Id == a.Type.ParentId &&
a.Type.Parent.Types.AsSelect().Where(b => b.Name == a.Title).Any(b => b.ParentId == a.Type.Parent.Id)
);
collectionSelect.ToList();
} }
[Fact] [Fact]
public void Count() { public void Count() {

View File

@ -138,6 +138,22 @@ namespace FreeSql.Tests.PostgreSQL {
var count = select.Where(a => 1 == 1).Count(); var count = select.Where(a => 1 == 1).Count();
Assert.False(select.Where(a => 1 == 2).Any()); Assert.False(select.Where(a => 1 == 2).Any());
Assert.Equal(count > 0, select.Where(a => 1 == 1).Any()); Assert.Equal(count > 0, select.Where(a => 1 == 1).Any());
var sql2222 = select.Where(a =>
select.Where(b => b.Id == a.Id &&
select.Where(c => c.Id == b.Id).Where(d => d.Id == a.Id).Where(e => e.Id == b.Id)
.Offset(a.Id)
.Any()
).Any(c => c.Id == a.Id + 10)
);
var sql2222Tolist = sql2222.ToList();
var collectionSelect = select.Where(a =>
a.Type.Guid == a.TestTypeInfoGuid &&
a.Type.Parent.Id == a.Type.ParentId &&
a.Type.Parent.Types.AsSelect().Where(b => b.Name == a.Title).Any(b => b.ParentId == a.Type.Parent.Id)
);
collectionSelect.ToList();
} }
[Fact] [Fact]
public void Count() { public void Count() {

View File

@ -71,6 +71,22 @@ namespace FreeSql.Tests.SqlServer {
var count = select.Where(a => 1 == 1).Count(); var count = select.Where(a => 1 == 1).Count();
Assert.False(select.Where(a => 1 == 2).Any()); Assert.False(select.Where(a => 1 == 2).Any());
Assert.Equal(count > 0, select.Where(a => 1 == 1).Any()); Assert.Equal(count > 0, select.Where(a => 1 == 1).Any());
var sql2222 = select.Where(a =>
select.Where(b => b.Id == a.Id &&
select.Where(c => c.Id == b.Id).Where(d => d.Id == a.Id).Where(e => e.Id == b.Id)
.Offset(a.Id)
.Any()
).Any(c => c.Id == a.Id + 10)
);
var sql2222Tolist = sql2222.ToList();
var collectionSelect = select.Where(a =>
a.Type.Guid == a.TestTypeInfoGuid &&
a.Type.Parent.Id == a.Type.ParentId &&
a.Type.Parent.Types.AsSelect().Where(b => b.Name == a.Title).Any(b => b.ParentId == a.Type.Parent.Id)
);
collectionSelect.ToList();
} }
[Fact] [Fact]
public void Count() { public void Count() {

View File

@ -102,6 +102,22 @@ namespace FreeSql.Tests.Sqlite {
var count = select.Where(a => 1 == 1).Count(); var count = select.Where(a => 1 == 1).Count();
Assert.False(select.Where(a => 1 == 2).Any()); Assert.False(select.Where(a => 1 == 2).Any());
Assert.Equal(count > 0, select.Where(a => 1 == 1).Any()); Assert.Equal(count > 0, select.Where(a => 1 == 1).Any());
var sql2222 = select.Where(a =>
select.Where(b => b.Id == a.Id &&
select.Where(c => c.Id == b.Id).Where(d => d.Id == a.Id).Where(e => e.Id == b.Id)
.Offset(a.Id)
.Any()
).Any(c => c.Id == a.Id + 10)
);
var sql2222Tolist = sql2222.ToList();
var collectionSelect = select.Where(a =>
a.Type.Guid == a.TestTypeInfoGuid &&
a.Type.Parent.Id == a.Type.ParentId &&
a.Type.Parent.Types.AsSelect().Where(b => b.Name == a.Title).Any(b => b.ParentId == a.Type.Parent.Id)
);
collectionSelect.ToList();
} }
[Fact] [Fact]
public void Count() { public void Count() {

View File

@ -27,15 +27,22 @@ namespace FreeSql.Tests {
public virtual Order Order { get; set; } public virtual Order Order { get; set; }
} }
class NullAggreTestTable {
[Column(IsIdentity = true)]
public int Id { get; set; }
}
ISelect<TestInfo> select => g.mysql.Select<TestInfo>(); ISelect<TestInfo> select => g.mysql.Select<TestInfo>();
[Fact] [Fact]
public void Test1() { public void Test1() {
var collSelect1 = g.mysql.Select<Order>().Where(a =>
a.OrderDetails.AsSelect().Where(b => b.OrderId == a.OrderID).Any()
);
var collectionSelect = select.Where(a =>
a.Type.Guid == a.TypeGuid &&
a.Type.Parent.Id == a.Type.ParentId &&
a.Type.Parent.Types.AsSelect().Where(b => b.Name == a.Title).Any(b => b.ParentId == a.Type.Parent.Id)
);
var order = g.mysql.Select<Order>().Where(a => a.OrderID == 1).ToOne(); //查询订单表 var order = g.mysql.Select<Order>().Where(a => a.OrderID == 1).ToOne(); //查询订单表
var orderDetail1 = order.OrderDetails; //第一次访问,查询数据库 var orderDetail1 = order.OrderDetails; //第一次访问,查询数据库
var orderDetail2 = order.OrderDetails; //第二次访问,不查 var orderDetail2 = order.OrderDetails; //第二次访问,不查
@ -182,6 +189,11 @@ namespace FreeSql.Tests {
} }
} }
class NullAggreTestTable {
[Column(IsIdentity = true)]
public int Id { get; set; }
}
[Table(Name = "xxx", SelectFilter = " a.id > 0")] [Table(Name = "xxx", SelectFilter = " a.id > 0")]
class TestInfo { class TestInfo {

View File

@ -1,4 +1,5 @@
using System; using FreeSql;
using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
@ -73,4 +74,17 @@ public static class FreeSqlGlobalExtensions {
} }
return ret; return ret;
} }
/// <summary>
/// 将 IEnumable<T> 转成 ISelect<T>,以便使用 FreeSql 的查询功能。此方法用于 Lambad 表达式中,快速进行集合导航的查询。
/// </summary>
/// <typeparam name="TEntity"></typeparam>
/// <param name="that"></param>
/// <returns></returns>
public static ISelect<TEntity> AsSelect<TEntity>(this IEnumerable<TEntity> that) where TEntity : class {
throw new NotImplementedException();
}
public static ISelect<TEntity> AsSelect<TEntity>(this IEnumerable<TEntity> that, IFreeSql orm = null) where TEntity : class {
return orm?.Select<TEntity>();
}
} }

View File

@ -1,5 +1,6 @@
using FreeSql.Internal.Model; using FreeSql.Internal.Model;
using System; using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data.Common; using System.Data.Common;
using System.Linq; using System.Linq;
@ -236,12 +237,18 @@ namespace FreeSql.Internal {
} }
if (callType.FullName.StartsWith("FreeSql.ISelect`")) { //子表查询 if (callType.FullName.StartsWith("FreeSql.ISelect`")) { //子表查询
if (exp3.Method.Name == "Any") { //exists if (exp3.Method.Name == "Any") { //exists
var anyArgs = exp3.Arguments;
var exp3Stack = new Stack<Expression>(); var exp3Stack = new Stack<Expression>();
var exp3tmp = exp3.Object; var exp3tmp = exp3.Object;
if (exp3tmp != null && anyArgs.Any())
exp3Stack.Push(Expression.Call(exp3tmp, callType.GetMethod("Where", anyArgs.Select(a => a.Type).ToArray()), anyArgs.ToArray()));
while (exp3tmp != null) { while (exp3tmp != null) {
exp3Stack.Push(exp3tmp); exp3Stack.Push(exp3tmp);
switch (exp3tmp.NodeType) { switch (exp3tmp.NodeType) {
case ExpressionType.Call: exp3tmp = (exp3tmp as MethodCallExpression).Object; continue; case ExpressionType.Call:
var exp3tmpCall = (exp3tmp as MethodCallExpression);
exp3tmp = exp3tmpCall.Object == null ? exp3tmpCall.Arguments.FirstOrDefault() : exp3tmpCall.Object;
continue;
case ExpressionType.MemberAccess: exp3tmp = (exp3tmp as MemberExpression).Expression; continue; case ExpressionType.MemberAccess: exp3tmp = (exp3tmp as MemberExpression).Expression; continue;
} }
break; break;
@ -253,7 +260,19 @@ namespace FreeSql.Internal {
while (exp3Stack.Any()) { while (exp3Stack.Any()) {
exp3tmp = exp3Stack.Pop(); exp3tmp = exp3Stack.Pop();
if (exp3tmp.Type.FullName.StartsWith("FreeSql.ISelect`") && fsql == null) { if (exp3tmp.Type.FullName.StartsWith("FreeSql.ISelect`") && fsql == null) {
fsql = Expression.Lambda(exp3tmp).Compile().DynamicInvoke(); if (exp3tmp.NodeType == ExpressionType.Call) {
var exp3tmpCall = (exp3tmp as MethodCallExpression);
if (exp3tmpCall.Method.Name == "AsSelect" && exp3tmpCall.Object == null) {
var exp3tmpArg1Type = exp3tmpCall.Arguments.FirstOrDefault()?.Type;
if (exp3tmpArg1Type != null) {
var exp3tmpEleType = exp3tmpArg1Type.GetElementType() ?? exp3tmpArg1Type.GenericTypeArguments.FirstOrDefault();
if (exp3tmpEleType != null) {
fsql = typeof(IFreeSql).GetMethod("Select", new Type[0]).MakeGenericMethod(exp3tmpEleType).Invoke(_common._orm, null);
}
}
}
}
if (fsql == null) fsql = Expression.Lambda(exp3tmp).Compile().DynamicInvoke();
fsqlType = fsql?.GetType(); fsqlType = fsql?.GetType();
if (fsqlType == null) break; if (fsqlType == null) break;
fsqlType.GetField("_limit", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(fsql, 1); fsqlType.GetField("_limit", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(fsql, 1);
@ -295,6 +314,12 @@ namespace FreeSql.Internal {
} }
} }
} }
var eleType = callType.GetElementType() ?? callType.GenericTypeArguments.FirstOrDefault();
if (eleType != null && typeof(IEnumerable<>).MakeGenericType(eleType).IsAssignableFrom(callType)) { //集合导航属性子查询
if (exp3.Method.Name == "Any") { //exists
}
}
var other3Exp = ExpressionLambdaToSqlOther(exp3, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName); var other3Exp = ExpressionLambdaToSqlOther(exp3, _tables, _selectColumnMap, getSelectGroupingMapString, tbtype, isQuoteName);
if (string.IsNullOrEmpty(other3Exp) == false) return other3Exp; if (string.IsNullOrEmpty(other3Exp) == false) return other3Exp;
throw new Exception($"未实现函数表达式 {exp3} 解析"); throw new Exception($"未实现函数表达式 {exp3} 解析");