mirror of
https://github.com/nsnail/FreeSql.git
synced 2025-04-22 02:32:50 +08:00
- 增加 linq to sql 的查询语法,以及单元测试;
This commit is contained in:
parent
7a625be8c9
commit
59b1b7220d
187
FreeSql.Tests/LinqToSql/SqliteLinqToSqlTests.cs
Normal file
187
FreeSql.Tests/LinqToSql/SqliteLinqToSqlTests.cs
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
using FreeSql.DataAnnotations;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace FreeSql.Tests.LinqToSql {
|
||||||
|
|
||||||
|
|
||||||
|
class TestLinqToSql {
|
||||||
|
public Guid id { get; set; }
|
||||||
|
|
||||||
|
public string name { get; set; }
|
||||||
|
|
||||||
|
public int click { get; set; } = 10;
|
||||||
|
|
||||||
|
public DateTime createtime { get; set; } = DateTime.Now;
|
||||||
|
}
|
||||||
|
class TestLinqToSqlComment {
|
||||||
|
public Guid id { get; set; }
|
||||||
|
|
||||||
|
public Guid TestLinqToSqlId { get; set; }
|
||||||
|
public TestLinqToSql TEstLinqToSql { get; set; }
|
||||||
|
|
||||||
|
public string text { get; set; }
|
||||||
|
|
||||||
|
public DateTime createtime { get; set; } = DateTime.Now;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class SqliteLinqToSqlTests {
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Where() {
|
||||||
|
var item = new TestLinqToSql { name = Guid.NewGuid().ToString() };
|
||||||
|
g.sqlite.Insert<TestLinqToSql>().AppendData(item).ExecuteAffrows();
|
||||||
|
|
||||||
|
var t1 = (from a in g.sqlite.Select<TestLinqToSql>()
|
||||||
|
where a.id == item.id
|
||||||
|
select a).ToList();
|
||||||
|
Assert.True(t1.Any());
|
||||||
|
Assert.Equal(item.id, t1[0].id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Select() {
|
||||||
|
var item = new TestLinqToSql { name = Guid.NewGuid().ToString() };
|
||||||
|
g.sqlite.Insert<TestLinqToSql>().AppendData(item).ExecuteAffrows();
|
||||||
|
|
||||||
|
var t1 = (from a in g.sqlite.Select<TestLinqToSql>()
|
||||||
|
where a.id == item.id
|
||||||
|
select new { a.id }).ToList();
|
||||||
|
Assert.True(t1.Any());
|
||||||
|
Assert.Equal(item.id, t1[0].id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void GroupBy() {
|
||||||
|
var item = new TestLinqToSql { name = Guid.NewGuid().ToString() };
|
||||||
|
g.sqlite.Insert<TestLinqToSql>().AppendData(item).ExecuteAffrows();
|
||||||
|
|
||||||
|
var t1 = (from a in g.sqlite.Select<TestLinqToSql>()
|
||||||
|
where a.id == item.id
|
||||||
|
group a by new {a.id, a.name } into g
|
||||||
|
select new {
|
||||||
|
g.Key.id, g.Key.name,
|
||||||
|
cou = g.Count(),
|
||||||
|
avg = g.Avg(g.Value.click),
|
||||||
|
sum = g.Sum(g.Value.click),
|
||||||
|
max = g.Max(g.Value.click),
|
||||||
|
min = g.Min(g.Value.click)
|
||||||
|
}).ToList();
|
||||||
|
Assert.True(t1.Any());
|
||||||
|
Assert.Equal(item.id, t1.First().id);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CaseWhen() {
|
||||||
|
var item = new TestLinqToSql { name = Guid.NewGuid().ToString() };
|
||||||
|
g.sqlite.Insert<TestLinqToSql>().AppendData(item).ExecuteAffrows();
|
||||||
|
|
||||||
|
var t1 = (from a in g.sqlite.Select<TestLinqToSql>()
|
||||||
|
where a.id == item.id
|
||||||
|
select new {
|
||||||
|
a.id,
|
||||||
|
a.name,
|
||||||
|
testsub = new {
|
||||||
|
time = a.click > 10 ? "大于" : "小于或等于"
|
||||||
|
}
|
||||||
|
}).ToList();
|
||||||
|
Assert.True(t1.Any());
|
||||||
|
Assert.Equal(item.id, t1[0].id);
|
||||||
|
Assert.Equal("小于或等于", t1[0].testsub.time);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Join() {
|
||||||
|
var item = new TestLinqToSql { name = Guid.NewGuid().ToString() };
|
||||||
|
g.sqlite.Insert<TestLinqToSql>().AppendData(item).ExecuteAffrows();
|
||||||
|
var comment = new TestLinqToSqlComment { TestLinqToSqlId = item.id, text = Guid.NewGuid().ToString() };
|
||||||
|
g.sqlite.Insert<TestLinqToSqlComment>().AppendData(comment).ExecuteAffrows();
|
||||||
|
|
||||||
|
var t1 = (from a in g.sqlite.Select<TestLinqToSql>()
|
||||||
|
join b in g.sqlite.Select<TestLinqToSqlComment>() on a.id equals b.TestLinqToSqlId
|
||||||
|
select a).ToList();
|
||||||
|
Assert.True(t1.Any());
|
||||||
|
//Assert.Equal(item.id, t1[0].id);
|
||||||
|
|
||||||
|
var t2 = (from a in g.sqlite.Select<TestLinqToSql>()
|
||||||
|
join b in g.sqlite.Select<TestLinqToSqlComment>() on a.id equals b.TestLinqToSqlId
|
||||||
|
select new { a.id, bid = b.id }).ToList();
|
||||||
|
Assert.True(t2.Any());
|
||||||
|
//Assert.Equal(item.id, t2[0].id);
|
||||||
|
//Assert.Equal(comment.id, t2[0].bid);
|
||||||
|
|
||||||
|
var t3 = (from a in g.sqlite.Select<TestLinqToSql>()
|
||||||
|
join b in g.sqlite.Select<TestLinqToSqlComment>() on a.id equals b.TestLinqToSqlId
|
||||||
|
where a.id == item.id
|
||||||
|
select new { a.id, bid = b.id }).ToList();
|
||||||
|
Assert.True(t3.Any());
|
||||||
|
Assert.Equal(item.id, t3[0].id);
|
||||||
|
Assert.Equal(comment.id, t3[0].bid);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void LeftJoin() {
|
||||||
|
var item = new TestLinqToSql { name = Guid.NewGuid().ToString() };
|
||||||
|
g.sqlite.Insert<TestLinqToSql>().AppendData(item).ExecuteAffrows();
|
||||||
|
var comment = new TestLinqToSqlComment { TestLinqToSqlId = item.id, text = Guid.NewGuid().ToString() };
|
||||||
|
g.sqlite.Insert<TestLinqToSqlComment>().AppendData(comment).ExecuteAffrows();
|
||||||
|
|
||||||
|
var t1 = (from a in g.sqlite.Select<TestLinqToSql>()
|
||||||
|
join b in g.sqlite.Select<TestLinqToSqlComment>() on a.id equals b.TestLinqToSqlId into temp
|
||||||
|
from tc in temp.DefaultIfEmpty()
|
||||||
|
select a).ToList();
|
||||||
|
Assert.True(t1.Any());
|
||||||
|
//Assert.Equal(item.id, t1[0].id);
|
||||||
|
|
||||||
|
var t2 = (from a in g.sqlite.Select<TestLinqToSql>()
|
||||||
|
join b in g.sqlite.Select<TestLinqToSqlComment>() on a.id equals b.TestLinqToSqlId into temp
|
||||||
|
from tc in temp.DefaultIfEmpty()
|
||||||
|
select new { a.id, bid = tc.id }).ToList();
|
||||||
|
Assert.True(t2.Any());
|
||||||
|
//Assert.Equal(item.id, t2[0].id);
|
||||||
|
//Assert.Equal(comment.id, t2[0].bid);
|
||||||
|
|
||||||
|
var t3 = (from a in g.sqlite.Select<TestLinqToSql>()
|
||||||
|
join b in g.sqlite.Select<TestLinqToSqlComment>() on a.id equals b.TestLinqToSqlId into temp
|
||||||
|
from tc in temp.DefaultIfEmpty()
|
||||||
|
where a.id == item.id
|
||||||
|
select new { a.id, bid = tc.id }).ToList();
|
||||||
|
Assert.True(t3.Any());
|
||||||
|
Assert.Equal(item.id, t3[0].id);
|
||||||
|
Assert.Equal(comment.id, t3[0].bid);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void From() {
|
||||||
|
var item = new TestLinqToSql { name = Guid.NewGuid().ToString() };
|
||||||
|
g.sqlite.Insert<TestLinqToSql>().AppendData(item).ExecuteAffrows();
|
||||||
|
var comment = new TestLinqToSqlComment { TestLinqToSqlId = item.id, text = Guid.NewGuid().ToString() };
|
||||||
|
g.sqlite.Insert<TestLinqToSqlComment>().AppendData(comment).ExecuteAffrows();
|
||||||
|
|
||||||
|
var t1 = (from a in g.sqlite.Select<TestLinqToSql>()
|
||||||
|
from b in g.sqlite.Select<TestLinqToSqlComment>()
|
||||||
|
where a.id == b.TestLinqToSqlId
|
||||||
|
select a).ToList();
|
||||||
|
Assert.True(t1.Any());
|
||||||
|
//Assert.Equal(item.id, t1[0].id);
|
||||||
|
|
||||||
|
var t2 = (from a in g.sqlite.Select<TestLinqToSql>()
|
||||||
|
from b in g.sqlite.Select<TestLinqToSqlComment>()
|
||||||
|
where a.id == b.TestLinqToSqlId
|
||||||
|
select new { a.id, bid = b.id }).ToList();
|
||||||
|
Assert.True(t2.Any());
|
||||||
|
//Assert.Equal(item.id, t2[0].id);
|
||||||
|
//Assert.Equal(comment.id, t2[0].bid);
|
||||||
|
|
||||||
|
var t3 = (from a in g.sqlite.Select<TestLinqToSql>()
|
||||||
|
from b in g.sqlite.Select<TestLinqToSqlComment>()
|
||||||
|
where a.id == b.TestLinqToSqlId
|
||||||
|
where a.id == item.id
|
||||||
|
select new { a.id, bid = b.id }).ToList();
|
||||||
|
Assert.True(t3.Any());
|
||||||
|
Assert.Equal(item.id, t3[0].id);
|
||||||
|
Assert.Equal(comment.id, t3[0].bid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -88,6 +88,18 @@ namespace FreeSql.Tests {
|
|||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Test1() {
|
public void Test1() {
|
||||||
|
var linqto1 =
|
||||||
|
from p in g.sqlite.Select<Order>()
|
||||||
|
where p.Id >= 0
|
||||||
|
// && p.OrderDetails.AsSelect().Where(c => c.Id > 10).Any()
|
||||||
|
orderby p.Id descending
|
||||||
|
orderby p.CustomerName ascending
|
||||||
|
select new { Name = p.CustomerName, Length = p.Id };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var testddd = new TestEntity {
|
var testddd = new TestEntity {
|
||||||
Test = 22,
|
Test = 22,
|
||||||
|
@ -27,6 +27,7 @@ public static class FreeSqlGlobalExtensions {
|
|||||||
});
|
});
|
||||||
public static bool IsNumberType(this Type that) => that == null ? false : dicIsNumberType.Value.ContainsKey(that);
|
public static bool IsNumberType(this Type that) => that == null ? false : dicIsNumberType.Value.ContainsKey(that);
|
||||||
public static bool IsNullableType(this Type that) => that?.FullName.StartsWith("System.Nullable`1[") == true;
|
public static bool IsNullableType(this Type that) => that?.FullName.StartsWith("System.Nullable`1[") == true;
|
||||||
|
public static bool IsAnonymousType(this Type that) => that?.FullName.StartsWith("<>f__AnonymousType") == true;
|
||||||
internal static Type NullableTypeOrThis(this Type that) => that?.IsNullableType() == true ? that.GenericTypeArguments.First() : that;
|
internal static Type NullableTypeOrThis(this Type that) => that?.IsNullableType() == true ? that.GenericTypeArguments.First() : that;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<Version>0.5.8</Version>
|
<Version>0.5.9</Version>
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
<Authors>YeXiangQin</Authors>
|
<Authors>YeXiangQin</Authors>
|
||||||
<Description>FreeSql is the most convenient ORM in dotnet. It supports Mysql, Postgresql, SqlServer, Oracle and Sqlite.</Description>
|
<Description>FreeSql is the most convenient ORM in dotnet. It supports Mysql, Postgresql, SqlServer, Oracle and Sqlite.</Description>
|
||||||
|
@ -963,6 +963,31 @@
|
|||||||
<param name="select">选择列</param>
|
<param name="select">选择列</param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:FreeSql.ISelect`1.Select``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
|
||||||
|
<summary>
|
||||||
|
【linq to sql】专用方法,不建议直接使用
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:FreeSql.ISelect`1.Join``3(FreeSql.ISelect{``0},System.Linq.Expressions.Expression{System.Func{`0,``1}},System.Linq.Expressions.Expression{System.Func{``0,``1}},System.Linq.Expressions.Expression{System.Func{`0,``0,``2}})">
|
||||||
|
<summary>
|
||||||
|
【linq to sql】专用方法,不建议直接使用
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:FreeSql.ISelect`1.GroupJoin``3(FreeSql.ISelect{``0},System.Linq.Expressions.Expression{System.Func{`0,``1}},System.Linq.Expressions.Expression{System.Func{``0,``1}},System.Linq.Expressions.Expression{System.Func{`0,FreeSql.ISelect{``0},``2}})">
|
||||||
|
<summary>
|
||||||
|
【linq to sql】专用方法,不建议直接使用
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:FreeSql.ISelect`1.DefaultIfEmpty">
|
||||||
|
<summary>
|
||||||
|
【linq to sql】专用方法,不建议直接使用
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
|
<member name="M:FreeSql.ISelect`1.SelectMany``2(System.Linq.Expressions.Expression{System.Func{`0,FreeSql.ISelect{``0}}},System.Linq.Expressions.Expression{System.Func{`0,``0,``1}})">
|
||||||
|
<summary>
|
||||||
|
【linq to sql】专用方法,不建议直接使用
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="M:FreeSql.ISelect`1.ToOne``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
|
<member name="M:FreeSql.ISelect`1.ToOne``1(System.Linq.Expressions.Expression{System.Func{`0,``0}})">
|
||||||
<summary>
|
<summary>
|
||||||
执行SQL查询,返回指定字段的记录的第一条记录,记录不存在时返回 TReturn 默认值
|
执行SQL查询,返回指定字段的记录的第一条记录,记录不存在时返回 TReturn 默认值
|
||||||
@ -1291,6 +1316,11 @@
|
|||||||
<param name="select">选择列</param>
|
<param name="select">选择列</param>
|
||||||
<returns></returns>
|
<returns></returns>
|
||||||
</member>
|
</member>
|
||||||
|
<member name="M:FreeSql.ISelectGrouping`2.Select``1(System.Linq.Expressions.Expression{System.Func{FreeSql.ISelectGroupingAggregate{`0,`1},``0}})">
|
||||||
|
<summary>
|
||||||
|
【linq to sql】专用方法,不建议直接使用
|
||||||
|
</summary>
|
||||||
|
</member>
|
||||||
<member name="M:FreeSql.ISelectGrouping`2.ToSql``1(System.Linq.Expressions.Expression{System.Func{FreeSql.ISelectGroupingAggregate{`0,`1},``0}})">
|
<member name="M:FreeSql.ISelectGrouping`2.ToSql``1(System.Linq.Expressions.Expression{System.Func{FreeSql.ISelectGroupingAggregate{`0,`1},``0}})">
|
||||||
<summary>
|
<summary>
|
||||||
返回即将执行的SQL语句
|
返回即将执行的SQL语句
|
||||||
|
@ -31,6 +31,27 @@ namespace FreeSql {
|
|||||||
List<TReturn> ToList<TReturn>(Expression<Func<T1, TReturn>> select);
|
List<TReturn> ToList<TReturn>(Expression<Func<T1, TReturn>> select);
|
||||||
Task<List<TReturn>> ToListAsync<TReturn>(Expression<Func<T1, TReturn>> select);
|
Task<List<TReturn>> ToListAsync<TReturn>(Expression<Func<T1, TReturn>> select);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 【linq to sql】专用方法,不建议直接使用
|
||||||
|
/// </summary>
|
||||||
|
ISelect<TReturn> Select<TReturn>(Expression<Func<T1, TReturn>> select) where TReturn : class;
|
||||||
|
/// <summary>
|
||||||
|
/// 【linq to sql】专用方法,不建议直接使用
|
||||||
|
/// </summary>
|
||||||
|
ISelect<TResult> Join<TInner, TKey, TResult>(ISelect<TInner> inner, Expression<Func<T1, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<T1, TInner, TResult>> resultSelector) where TInner : class where TResult : class;
|
||||||
|
/// <summary>
|
||||||
|
/// 【linq to sql】专用方法,不建议直接使用
|
||||||
|
/// </summary>
|
||||||
|
ISelect<TResult> GroupJoin<TInner, TKey, TResult>(ISelect<TInner> inner, Expression<Func<T1, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<T1, ISelect<TInner>, TResult>> resultSelector) where TInner : class where TResult : class;
|
||||||
|
/// <summary>
|
||||||
|
/// 【linq to sql】专用方法,不建议直接使用
|
||||||
|
/// </summary>
|
||||||
|
ISelect<T1> DefaultIfEmpty();
|
||||||
|
/// <summary>
|
||||||
|
/// 【linq to sql】专用方法,不建议直接使用
|
||||||
|
/// </summary>
|
||||||
|
ISelect<TResult> SelectMany<TCollection, TResult>(Expression<Func<T1, ISelect<TCollection>>> collectionSelector, Expression<Func<T1, TCollection, TResult>> resultSelector) where TCollection : class where TResult : class;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 执行SQL查询,返回指定字段的记录的第一条记录,记录不存在时返回 TReturn 默认值
|
/// 执行SQL查询,返回指定字段的记录的第一条记录,记录不存在时返回 TReturn 默认值
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -36,6 +36,11 @@ namespace FreeSql {
|
|||||||
List<TReturn> ToList<TReturn>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TReturn>> select);
|
List<TReturn> ToList<TReturn>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TReturn>> select);
|
||||||
Task<List<TReturn>> ToListAsync<TReturn>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TReturn>> select);
|
Task<List<TReturn>> ToListAsync<TReturn>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TReturn>> select);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 【linq to sql】专用方法,不建议直接使用
|
||||||
|
/// </summary>
|
||||||
|
List<TReturn> Select<TReturn>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TReturn>> select);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 返回即将执行的SQL语句
|
/// 返回即将执行的SQL语句
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -770,7 +770,7 @@ namespace FreeSql.Internal {
|
|||||||
if (mp?.Expression != null) { //导航条件,OneToOne、ManyToOne
|
if (mp?.Expression != null) { //导航条件,OneToOne、ManyToOne
|
||||||
var firstTb = tsc._tables.First().Table;
|
var firstTb = tsc._tables.First().Table;
|
||||||
var parentTb = _common.GetTableByEntity(mp.Expression.Type);
|
var parentTb = _common.GetTableByEntity(mp.Expression.Type);
|
||||||
var parentTbRef = parentTb.GetTableRef(mp.Member.Name, tsc.style == ExpressionStyle.AsSelect);
|
var parentTbRef = parentTb?.GetTableRef(mp.Member.Name, tsc.style == ExpressionStyle.AsSelect);
|
||||||
if (parentTbRef != null) {
|
if (parentTbRef != null) {
|
||||||
Expression navCondExp = null;
|
Expression navCondExp = null;
|
||||||
for (var mn = 0; mn < parentTbRef.Columns.Count; mn++) {
|
for (var mn = 0; mn < parentTbRef.Columns.Count; mn++) {
|
||||||
|
@ -31,6 +31,7 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
protected DbConnection _connection;
|
protected DbConnection _connection;
|
||||||
protected Action<object> _trackToList;
|
protected Action<object> _trackToList;
|
||||||
protected bool _distinct;
|
protected bool _distinct;
|
||||||
|
protected Expression _selectExpression;
|
||||||
|
|
||||||
internal static void CopyData(Select0Provider<TSelect, T1> from, object to, ReadOnlyCollection<ParameterExpression> lambParms) {
|
internal static void CopyData(Select0Provider<TSelect, T1> from, object to, ReadOnlyCollection<ParameterExpression> lambParms) {
|
||||||
var toType = to?.GetType();
|
var toType = to?.GetType();
|
||||||
@ -43,19 +44,22 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
toType.GetField("_having", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._having);
|
toType.GetField("_having", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._having);
|
||||||
toType.GetField("_where", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new StringBuilder().Append(from._where.ToString()));
|
toType.GetField("_where", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new StringBuilder().Append(from._where.ToString()));
|
||||||
toType.GetField("_params", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new List<DbParameter>(from._params.ToArray()));
|
toType.GetField("_params", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new List<DbParameter>(from._params.ToArray()));
|
||||||
//toType.GetField("_tables", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new List<SelectTableInfo>(from._tables.ToArray()));
|
if (lambParms == null)
|
||||||
var _multiTables = toType.GetField("_tables", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(to) as List<SelectTableInfo>;
|
toType.GetField("_tables", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new List<SelectTableInfo>(from._tables.ToArray()));
|
||||||
_multiTables[0] = from._tables[0];
|
else {
|
||||||
for (var a = 1; a < lambParms.Count; a++) {
|
var _multiTables = toType.GetField("_tables", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(to) as List<SelectTableInfo>;
|
||||||
var tb = from._tables.Where(b => b.Alias == lambParms[a].Name && b.Table.Type == lambParms[a].Type).FirstOrDefault();
|
_multiTables[0] = from._tables[0];
|
||||||
if (tb != null) _multiTables[a] = tb;
|
for (var a = 1; a < lambParms.Count; a++) {
|
||||||
else {
|
var tb = from._tables.Where(b => b.Alias == lambParms[a].Name && b.Table.Type == lambParms[a].Type).FirstOrDefault();
|
||||||
_multiTables[a].Alias = lambParms[a].Name;
|
if (tb != null) _multiTables[a] = tb;
|
||||||
_multiTables[a].Parameter = lambParms[a];
|
else {
|
||||||
|
_multiTables[a].Alias = lambParms[a].Name;
|
||||||
|
_multiTables[a].Parameter = lambParms[a];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (_multiTables.Count < from._tables.Count)
|
||||||
|
_multiTables.AddRange(from._tables.GetRange(_multiTables.Count, from._tables.Count - _multiTables.Count));
|
||||||
}
|
}
|
||||||
if (_multiTables.Count < from._tables.Count)
|
|
||||||
_multiTables.AddRange(from._tables.GetRange(_multiTables.Count, from._tables.Count - _multiTables.Count));
|
|
||||||
toType.GetField("_tableRules", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._tableRules);
|
toType.GetField("_tableRules", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._tableRules);
|
||||||
toType.GetField("_join", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new StringBuilder().Append(from._join.ToString()));
|
toType.GetField("_join", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, new StringBuilder().Append(from._join.ToString()));
|
||||||
toType.GetField("_cache", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._cache);
|
toType.GetField("_cache", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._cache);
|
||||||
@ -66,6 +70,7 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
toType.GetField("_connection", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._connection);
|
toType.GetField("_connection", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._connection);
|
||||||
toType.GetField("_trackToList", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._trackToList);
|
toType.GetField("_trackToList", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._trackToList);
|
||||||
toType.GetField("_distinct", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._distinct);
|
toType.GetField("_distinct", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._distinct);
|
||||||
|
toType.GetField("_selectExpression", BindingFlags.Instance | BindingFlags.NonPublic)?.SetValue(to, from._selectExpression);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Select0Provider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) {
|
public Select0Provider(IFreeSql orm, CommonUtils commonUtils, CommonExpression commonExpression, object dywhere) {
|
||||||
@ -366,10 +371,14 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
return ret;
|
return ret;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
public List<T1> ToList(bool includeNestedMembers = false) =>
|
public List<T1> ToList(bool includeNestedMembers = false) {
|
||||||
this.ToListPrivate(includeNestedMembers == false ? this.GetAllFieldExpressionTreeLevel2() : this.GetAllFieldExpressionTreeLevelAll());
|
if (_selectExpression != null) return this.InternalToList<T1>(_selectExpression);
|
||||||
public Task<List<T1>> ToListAsync(bool includeNestedMembers = false) =>
|
return this.ToListPrivate(includeNestedMembers == false ? this.GetAllFieldExpressionTreeLevel2() : this.GetAllFieldExpressionTreeLevelAll());
|
||||||
this.ToListPrivateAsync(includeNestedMembers == false ? this.GetAllFieldExpressionTreeLevel2() : this.GetAllFieldExpressionTreeLevelAll());
|
}
|
||||||
|
public Task<List<T1>> ToListAsync(bool includeNestedMembers = false) {
|
||||||
|
if (_selectExpression != null) return this.InternalToListAsync<T1>(_selectExpression);
|
||||||
|
return this.ToListPrivateAsync(includeNestedMembers == false ? this.GetAllFieldExpressionTreeLevel2() : this.GetAllFieldExpressionTreeLevelAll());
|
||||||
|
}
|
||||||
public T1 ToOne() {
|
public T1 ToOne() {
|
||||||
this.Limit(1);
|
this.Limit(1);
|
||||||
return this.ToList().FirstOrDefault();
|
return this.ToList().FirstOrDefault();
|
||||||
|
@ -5,6 +5,7 @@ using System.Data;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace FreeSql.Internal.CommonProvider {
|
namespace FreeSql.Internal.CommonProvider {
|
||||||
@ -153,6 +154,70 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
return this.InternalToListAsync<TReturn>(select?.Body);
|
return this.InternalToListAsync<TReturn>(select?.Body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ISelect<TReturn> Select<TReturn>(Expression<Func<T1, TReturn>> select) where TReturn : class {
|
||||||
|
if (typeof(TReturn) == typeof(T1)) return this as ISelect<TReturn>;
|
||||||
|
_tables[0].Parameter = select.Parameters[0];
|
||||||
|
_selectExpression = select.Body;
|
||||||
|
var ret = _orm.Select<TReturn>();
|
||||||
|
Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, null);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
public ISelect<TResult> Join<TInner, TKey, TResult>(ISelect<TInner> inner, Expression<Func<T1, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<T1, TInner, TResult>> resultSelector) where TInner : class where TResult : class {
|
||||||
|
_tables[0].Parameter = resultSelector.Parameters[0];
|
||||||
|
_commonExpression.ExpressionLambdaToSql(outerKeySelector, new CommonExpression.ExpTSC { _tables = _tables });
|
||||||
|
this.InternalJoin(Expression.Lambda<Func<T1, TInner, bool>>(
|
||||||
|
Expression.Equal(outerKeySelector.Body, innerKeySelector.Body),
|
||||||
|
new[] { outerKeySelector.Parameters[0], innerKeySelector.Parameters[0] }
|
||||||
|
), SelectTableInfoType.InnerJoin);
|
||||||
|
if (typeof(TResult) == typeof(T1)) return this as ISelect<TResult>;
|
||||||
|
_selectExpression = resultSelector.Body;
|
||||||
|
var ret = _orm.Select<TResult>() as Select1Provider<TResult>;
|
||||||
|
Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, null);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
public ISelect<TResult> GroupJoin<TInner, TKey, TResult>(ISelect<TInner> inner, Expression<Func<T1, TKey>> outerKeySelector, Expression<Func<TInner, TKey>> innerKeySelector, Expression<Func<T1, ISelect<TInner>, TResult>> resultSelector) where TInner : class where TResult : class {
|
||||||
|
_tables[0].Parameter = resultSelector.Parameters[0];
|
||||||
|
_commonExpression.ExpressionLambdaToSql(outerKeySelector, new CommonExpression.ExpTSC { _tables = _tables });
|
||||||
|
this.InternalJoin(Expression.Lambda<Func<T1, TInner, bool>>(
|
||||||
|
Expression.Equal(outerKeySelector.Body, innerKeySelector.Body),
|
||||||
|
new[] { outerKeySelector.Parameters[0], innerKeySelector.Parameters[0] }
|
||||||
|
), SelectTableInfoType.InnerJoin);
|
||||||
|
if (typeof(TResult) == typeof(T1)) return this as ISelect<TResult>;
|
||||||
|
_selectExpression = resultSelector.Body;
|
||||||
|
var ret = _orm.Select<TResult>() as Select1Provider<TResult>;
|
||||||
|
Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, null);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
public ISelect<TResult> SelectMany<TCollection, TResult>(Expression<Func<T1, ISelect<TCollection>>> collectionSelector, Expression<Func<T1, TCollection, TResult>> resultSelector) where TCollection : class where TResult : class {
|
||||||
|
SelectTableInfo find = null;
|
||||||
|
if (collectionSelector.Body.NodeType == ExpressionType.Call) {
|
||||||
|
var callExp = collectionSelector.Body as MethodCallExpression;
|
||||||
|
if (callExp.Method.Name == "DefaultIfEmpty" && callExp.Object.Type.GenericTypeArguments.Any()) {
|
||||||
|
find = _tables.Where((a, idx) => idx > 0 && a.Type == SelectTableInfoType.InnerJoin && a.Table.Type == callExp.Object.Type.GenericTypeArguments[0]).LastOrDefault();
|
||||||
|
if (find != null) {
|
||||||
|
if (!string.IsNullOrEmpty(find.On)) find.On = Regex.Replace(find.On, $@"\b{find.Alias}\.", $"{resultSelector.Parameters[1].Name}.");
|
||||||
|
if (!string.IsNullOrEmpty(find.NavigateCondition)) find.NavigateCondition = Regex.Replace(find.NavigateCondition, $@"\b{find.Alias}\.", $"{resultSelector.Parameters[1].Name}.");
|
||||||
|
find.Type = SelectTableInfoType.LeftJoin;
|
||||||
|
find.Alias = resultSelector.Parameters[1].Name;
|
||||||
|
find.Parameter = resultSelector.Parameters[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (find == null) {
|
||||||
|
var tb = _commonUtils.GetTableByEntity(typeof(TCollection));
|
||||||
|
if (tb == null) throw new Exception($"SelectMany 错误的类型:{typeof(TCollection).FullName}");
|
||||||
|
_tables.Add(new SelectTableInfo { Alias = resultSelector.Parameters[1].Name, AliasInit = resultSelector.Parameters[1].Name, Parameter = resultSelector.Parameters[1], Table = tb, Type = SelectTableInfoType.From });
|
||||||
|
}
|
||||||
|
if (typeof(TResult) == typeof(T1)) return this as ISelect<TResult>;
|
||||||
|
_selectExpression = resultSelector.Body;
|
||||||
|
var ret = _orm.Select<TResult>() as Select1Provider<TResult>;
|
||||||
|
Select0Provider<ISelect<T1>, T1>.CopyData(this, ret, null);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
public ISelect<T1> DefaultIfEmpty() {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public DataTable ToDataTable<TReturn>(Expression<Func<T1, TReturn>> select) {
|
public DataTable ToDataTable<TReturn>(Expression<Func<T1, TReturn>> select) {
|
||||||
if (select == null) return this.InternalToDataTable(select?.Body);
|
if (select == null) return this.InternalToDataTable(select?.Body);
|
||||||
_tables[0].Parameter = select.Parameters[0];
|
_tables[0].Parameter = select.Parameters[0];
|
||||||
|
@ -110,6 +110,7 @@ namespace FreeSql.Internal.CommonProvider {
|
|||||||
method = method.MakeGenericMethod(typeof(TReturn));
|
method = method.MakeGenericMethod(typeof(TReturn));
|
||||||
return method.Invoke(_select, new object[] { (map, field.Length > 0 ? field.Remove(0, 2).ToString() : null) }) as Task<List<TReturn>>;
|
return method.Invoke(_select, new object[] { (map, field.Length > 0 ? field.Remove(0, 2).ToString() : null) }) as Task<List<TReturn>>;
|
||||||
}
|
}
|
||||||
|
public List<TReturn> Select<TReturn>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TReturn>> select) => ToList(select);
|
||||||
|
|
||||||
public string ToSql<TReturn>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TReturn>> select) {
|
public string ToSql<TReturn>(Expression<Func<ISelectGroupingAggregate<TKey, TValue>, TReturn>> select) {
|
||||||
var map = new ReadAnonymousTypeInfo();
|
var map = new ReadAnonymousTypeInfo();
|
||||||
|
@ -18,7 +18,7 @@ namespace FreeSql.Internal {
|
|||||||
|
|
||||||
static ConcurrentDictionary<DataType, ConcurrentDictionary<Type, TableInfo>> _cacheGetTableByEntity = new ConcurrentDictionary<DataType, ConcurrentDictionary<Type, TableInfo>>();
|
static ConcurrentDictionary<DataType, ConcurrentDictionary<Type, TableInfo>> _cacheGetTableByEntity = new ConcurrentDictionary<DataType, ConcurrentDictionary<Type, TableInfo>>();
|
||||||
internal static void RemoveTableByEntity(Type entity, CommonUtils common) {
|
internal static void RemoveTableByEntity(Type entity, CommonUtils common) {
|
||||||
if (entity.FullName.StartsWith("<>f__AnonymousType") ||
|
if (entity.IsAnonymousType() ||
|
||||||
entity.IsValueType ||
|
entity.IsValueType ||
|
||||||
entity.IsNullableType() ||
|
entity.IsNullableType() ||
|
||||||
entity.NullableTypeOrThis() == typeof(BigInteger)
|
entity.NullableTypeOrThis() == typeof(BigInteger)
|
||||||
@ -27,7 +27,7 @@ namespace FreeSql.Internal {
|
|||||||
if (tbc.TryRemove(entity, out var trytb) && trytb?.TypeLazy != null) tbc.TryRemove(trytb.TypeLazy, out var trylz);
|
if (tbc.TryRemove(entity, out var trytb) && trytb?.TypeLazy != null) tbc.TryRemove(trytb.TypeLazy, out var trylz);
|
||||||
}
|
}
|
||||||
internal static TableInfo GetTableByEntity(Type entity, CommonUtils common) {
|
internal static TableInfo GetTableByEntity(Type entity, CommonUtils common) {
|
||||||
if (entity.FullName.StartsWith("<>f__AnonymousType") ||
|
if (entity.IsAnonymousType() ||
|
||||||
entity.IsValueType ||
|
entity.IsValueType ||
|
||||||
entity.IsNullableType() ||
|
entity.IsNullableType() ||
|
||||||
entity.NullableTypeOrThis() == typeof(BigInteger)
|
entity.NullableTypeOrThis() == typeof(BigInteger)
|
||||||
|
@ -254,7 +254,7 @@ namespace FreeSql.Sqlite {
|
|||||||
public bool SyncStructure<TEntity>() => this.SyncStructure(typeof(TEntity));
|
public bool SyncStructure<TEntity>() => this.SyncStructure(typeof(TEntity));
|
||||||
public bool SyncStructure(params Type[] entityTypes) {
|
public bool SyncStructure(params Type[] entityTypes) {
|
||||||
if (entityTypes == null) return true;
|
if (entityTypes == null) return true;
|
||||||
var syncTypes = entityTypes.Where(a => dicSyced.ContainsKey(a.FullName) == false).ToArray();
|
var syncTypes = entityTypes.Where(a => a.IsAnonymousType() == false && dicSyced.ContainsKey(a.FullName) == false).ToArray();
|
||||||
if (syncTypes.Any() == false) return true;
|
if (syncTypes.Any() == false) return true;
|
||||||
var before = new Aop.SyncStructureBeforeEventArgs(entityTypes);
|
var before = new Aop.SyncStructureBeforeEventArgs(entityTypes);
|
||||||
_orm.Aop.SyncStructureBefore?.Invoke(this, before);
|
_orm.Aop.SyncStructureBefore?.Invoke(this, before);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user