diff --git a/FreeSql.DbContext/DbSet/DbSet.cs b/FreeSql.DbContext/DbSet/DbSet.cs index a25d4317..4dbe2715 100644 --- a/FreeSql.DbContext/DbSet/DbSet.cs +++ b/FreeSql.DbContext/DbSet/DbSet.cs @@ -68,7 +68,7 @@ namespace FreeSql internal void TrackToList(object list) { if (list == null) return; - var ls = list as IList; + var ls = list as IEnumerable; if (ls == null) { var ie = list as IEnumerable; diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs index fc638846..4fc799af 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.MySqlConnector/MySqlConnector/Curd/MySqlSelectTest.cs @@ -251,6 +251,18 @@ namespace FreeSql.Tests.MySqlConnector var t11 = select.Where(a => a.Type.Name.Length > 0).ToList(true); var t21 = select.Where(a => a.Type.Parent.Name.Length > 0).ToList(true); } + [Fact] + public void ToDictionary() + { + var testDto1 = select.Limit(10).ToDictionary(a => a.Id); + var testDto2 = select.Limit(10).ToDictionary(a => a.Id, a => new { a.Id, a.Title }); + + var repo = g.mysql.GetRepository(); + var dic = repo.Select.Limit(10).ToDictionary(a => a.Id); + var first = dic.First().Value; + first.Clicks++; + repo.Update(first); + } class TestGuidIdToList { public Guid id { get; set; } diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs index 79cd586c..314961b2 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Dameng/Curd/DamengSelectTest.cs @@ -192,6 +192,18 @@ namespace FreeSql.Tests.Odbc.Dameng var t11 = select.Where(a => a.Type.Name.Length > 0).ToList(true); var t21 = select.Where(a => a.Type.Parent.Name.Length > 0).ToList(true); } + [Fact] + public void ToDictionary() + { + var testDto1 = select.Limit(10).ToDictionary(a => a.Id); + var testDto2 = select.Limit(10).ToDictionary(a => a.Id, a => new { a.Id, a.Title }); + + var repo = g.dameng.GetRepository(); + var dic = repo.Select.Limit(10).ToDictionary(a => a.Id); + var first = dic.First().Value; + first.Clicks++; + repo.Update(first); + } class TestGuidIdToList { public Guid id { get; set; } diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Default/Curd/OdbcSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Default/Curd/OdbcSelectTest.cs index 8db28289..edb5cb2d 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Default/Curd/OdbcSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Default/Curd/OdbcSelectTest.cs @@ -183,6 +183,18 @@ namespace FreeSql.Tests.Odbc.Default var t11 = select.Where(a => a.Type.Name.Length > 0).ToList(true); var t21 = select.Where(a => a.Type.Parent.Name.Length > 0).ToList(true); } + [Fact] + public void ToDictionary() + { + var testDto1 = select.Limit(10).ToDictionary(a => a.Id); + var testDto2 = select.Limit(10).ToDictionary(a => a.Id, a => new { a.Id, a.Title }); + + var repo = g.odbc.GetRepository(); + var dic = repo.Select.Limit(10).ToDictionary(a => a.Id); + var first = dic.First().Value; + first.Clicks++; + repo.Update(first); + } class TestGuidIdToList { public Guid id { get; set; } diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs index 79e3e6ad..945f877d 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/MySql/Curd/MySqlSelectTest.cs @@ -292,6 +292,18 @@ namespace FreeSql.Tests.Odbc.MySql var t11 = select.Where(a => a.Type.Name.Length > 0).ToList(true); var t21 = select.Where(a => a.Type.Parent.Name.Length > 0).ToList(true); } + [Fact] + public void ToDictionary() + { + var testDto1 = select.Limit(10).ToDictionary(a => a.Id); + var testDto2 = select.Limit(10).ToDictionary(a => a.Id, a => new { a.Id, a.Title }); + + var repo = g.mysql.GetRepository(); + var dic = repo.Select.Limit(10).ToDictionary(a => a.Id); + var first = dic.First().Value; + first.Clicks++; + repo.Update(first); + } class TestGuidIdToList { public Guid id { get; set; } diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs index ec0fb836..3a8b0135 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/Oracle/Curd/OracleSelectTest.cs @@ -192,6 +192,18 @@ namespace FreeSql.Tests.Odbc.Oracle var t11 = select.Where(a => a.Type.Name.Length > 0).ToList(true); var t21 = select.Where(a => a.Type.Parent.Name.Length > 0).ToList(true); } + [Fact] + public void ToDictionary() + { + var testDto1 = select.Limit(10).ToDictionary(a => a.Id); + var testDto2 = select.Limit(10).ToDictionary(a => a.Id, a => new { a.Id, a.Title }); + + var repo = g.oracle.GetRepository(); + var dic = repo.Select.Limit(10).ToDictionary(a => a.Id); + var first = dic.First().Value; + first.Clicks++; + repo.Update(first); + } class TestGuidIdToList { public Guid id { get; set; } diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs index 545c0fa6..bb1db718 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/PostgreSQL/Curd/PostgreSQLSelectTest.cs @@ -268,6 +268,18 @@ namespace FreeSql.Tests.Odbc.PostgreSQL var t11 = select.Where(a => a.Type.Name.Length > 0).ToList(true); var t21 = select.Where(a => a.Type.Parent.Name.Length > 0).ToList(true); } + [Fact] + public void ToDictionary() + { + var testDto1 = select.Limit(10).ToDictionary(a => a.Id); + var testDto2 = select.Limit(10).ToDictionary(a => a.Id, a => new { a.Id, a.Title }); + + var repo = g.pgsql.GetRepository(); + var dic = repo.Select.Limit(10).ToDictionary(a => a.Id); + var first = dic.First().Value; + first.Clicks++; + repo.Update(first); + } class TestGuidIdToList { public Guid id { get; set; } diff --git a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs index 7b9f97af..3ac1ed9b 100644 --- a/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests.Provider.Odbc/SqlServer/Curd/SqlServerSelectTest.cs @@ -182,6 +182,18 @@ namespace FreeSql.Tests.Odbc.SqlServer var t11 = select.Where(a => a.Type.Name.Length > 0).ToList(true); var t21 = select.Where(a => a.Type.Parent.Name.Length > 0).ToList(true); } + [Fact] + public void ToDictionary() + { + var testDto1 = select.Limit(10).ToDictionary(a => a.Id); + var testDto2 = select.Limit(10).ToDictionary(a => a.Id, a => new { a.Id, a.Title }); + + var repo = g.sqlserver.GetRepository(); + var dic = repo.Select.Limit(10).ToDictionary(a => a.Id); + var first = dic.First().Value; + first.Clicks++; + repo.Update(first); + } class TestGuidIdToList { public Guid id { get; set; } diff --git a/FreeSql.Tests/FreeSql.Tests/MsAccess/Curd/MsAccessSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/MsAccess/Curd/MsAccessSelectTest.cs index 243d9eb0..bd238e73 100644 --- a/FreeSql.Tests/FreeSql.Tests/MsAccess/Curd/MsAccessSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/MsAccess/Curd/MsAccessSelectTest.cs @@ -183,6 +183,20 @@ namespace FreeSql.Tests.MsAccess var t11 = select.Where(a => a.Type.Name.Length > 0).ToList(true); var t21 = select.Where(a => a.Type.Parent.Name.Length > 0).ToList(true); } + [Fact] + public void ToDictionary() + { + var testDto1 = select.Limit(10).ToDictionary(a => a.Id); + var testDto2 = select.Limit(10).ToDictionary(a => a.Id, a=> new { a.Id, a.Title }); + var testDto11 = select.Limit(10).ToDictionaryAsync(a => a.Id).Result; + var testDto22 = select.Limit(10).ToDictionaryAsync(a => a.Id, a => new { a.Id, a.Title }).Result; + + var repo = g.msaccess.GetRepository(); + var dic = repo.Select.Limit(10).ToDictionary(a => a.Id); + var first = dic.First().Value; + first.Clicks++; + repo.Update(first); + } class TestGuidIdToList { public Guid id { get; set; } diff --git a/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs index 818e4196..4a419368 100644 --- a/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/MySql/Curd/MySqlSelectTest.cs @@ -292,6 +292,18 @@ namespace FreeSql.Tests.MySql var t11 = select.Where(a => a.Type.Name.Length > 0).ToList(true); var t21 = select.Where(a => a.Type.Parent.Name.Length > 0).ToList(true); } + [Fact] + public void ToDictionary() + { + var testDto1 = select.Limit(10).ToDictionary(a => a.Id); + var testDto2 = select.Limit(10).ToDictionary(a => a.Id, a => new { a.Id, a.Title }); + + var repo = g.mysql.GetRepository(); + var dic = repo.Select.Limit(10).ToDictionary(a => a.Id); + var first = dic.First().Value; + first.Clicks++; + repo.Update(first); + } class TestGuidIdToList { public Guid id { get; set; } diff --git a/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs index 942fb81f..011b3de7 100644 --- a/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Oracle/Curd/OracleSelectTest.cs @@ -192,6 +192,18 @@ namespace FreeSql.Tests.Oracle var t11 = select.Where(a => a.Type.Name.Length > 0).ToList(true); var t21 = select.Where(a => a.Type.Parent.Name.Length > 0).ToList(true); } + [Fact] + public void ToDictionary() + { + var testDto1 = select.Limit(10).ToDictionary(a => a.Id); + var testDto2 = select.Limit(10).ToDictionary(a => a.Id, a => new { a.Id, a.Title }); + + var repo = g.oracle.GetRepository(); + var dic = repo.Select.Limit(10).ToDictionary(a => a.Id); + var first = dic.First().Value; + first.Clicks++; + repo.Update(first); + } class TestGuidIdToList { public Guid id { get; set; } diff --git a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs index 75ffdfa5..346ab34a 100644 --- a/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/PostgreSQL/Curd/PostgreSQLSelectTest.cs @@ -268,6 +268,18 @@ namespace FreeSql.Tests.PostgreSQL var t11 = select.Where(a => a.Type.Name.Length > 0).ToList(true); var t21 = select.Where(a => a.Type.Parent.Name.Length > 0).ToList(true); } + [Fact] + public void ToDictionary() + { + var testDto1 = select.Limit(10).ToDictionary(a => a.Id); + var testDto2 = select.Limit(10).ToDictionary(a => a.Id, a => new { a.Id, a.Title }); + + var repo = g.pgsql.GetRepository(); + var dic = repo.Select.Limit(10).ToDictionary(a => a.Id); + var first = dic.First().Value; + first.Clicks++; + repo.Update(first); + } class TestGuidIdToList { public Guid id { get; set; } diff --git a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs index e55dc1a2..943de287 100644 --- a/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/SqlServer/Curd/SqlServerSelectTest.cs @@ -192,6 +192,18 @@ namespace FreeSql.Tests.SqlServer var t11 = select.Where(a => a.Type.Name.Length > 0).ToList(true); var t21 = select.Where(a => a.Type.Parent.Name.Length > 0).ToList(true); } + [Fact] + public void ToDictionary() + { + var testDto1 = select.Limit(10).ToDictionary(a => a.Id); + var testDto2 = select.Limit(10).ToDictionary(a => a.Id, a => new { a.Id, a.Title }); + + var repo = g.sqlserver.GetRepository(); + var dic = repo.Select.Limit(10).ToDictionary(a => a.Id); + var first = dic.First().Value; + first.Clicks++; + repo.Update(first); + } class TestGuidIdToList { public Guid id { get; set; } diff --git a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs index 5d138880..d7bb93e1 100644 --- a/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs +++ b/FreeSql.Tests/FreeSql.Tests/Sqlite/Curd/SqliteSelectTest.cs @@ -209,6 +209,18 @@ namespace FreeSql.Tests.Sqlite var t11 = select.Where(a => a.Type.Name.Length > 0).ToList(true); var t21 = select.Where(a => a.Type.Parent.Name.Length > 0).ToList(true); } + [Fact] + public void ToDictionary() + { + var testDto1 = select.Limit(10).ToDictionary(a => a.Id); + var testDto2 = select.Limit(10).ToDictionary(a => a.Id, a => new { a.Id, a.Title }); + + var repo = g.sqlite.GetRepository(); + var dic = repo.Select.Limit(10).ToDictionary(a => a.Id); + var first = dic.First().Value; + first.Clicks++; + repo.Update(first); + } class TestGuidIdToList { public Guid id { get; set; } diff --git a/FreeSql/FreeSql.xml b/FreeSql/FreeSql.xml index 4958b871..96d40ff9 100644 --- a/FreeSql/FreeSql.xml +++ b/FreeSql/FreeSql.xml @@ -1033,6 +1033,15 @@ + + + 以字典的形式返回查询结果 + 注意:字典的特点会导致 OrderBy 排序失效 + + + + + 执行SQL查询,返回 T1 实体所有字段的记录,记录不存在时返回 Count 为 0 的列表 diff --git a/FreeSql/Interface/Curd/ISelect/ISelect0.cs b/FreeSql/Interface/Curd/ISelect/ISelect0.cs index b42fc3c1..a9a98620 100644 --- a/FreeSql/Interface/Curd/ISelect/ISelect0.cs +++ b/FreeSql/Interface/Curd/ISelect/ISelect0.cs @@ -14,6 +14,8 @@ namespace FreeSql #if net40 #else Task ToDataTableAsync(string field = null); + Task> ToDictionaryAsync(Func keySelector); + Task> ToDictionaryAsync(Func keySelector, Func valueSelector); Task> ToListAsync(bool includeNestedMembers = false); Task> ToListAsync(string field); @@ -50,6 +52,15 @@ namespace FreeSql /// DataTable ToDataTable(string field = null); + /// + /// 以字典的形式返回查询结果 + /// 注意:字典的特点会导致 OrderBy 排序失效 + /// + /// + /// + /// + Dictionary ToDictionary(Func keySelector); + Dictionary ToDictionary(Func keySelector, Func valueSelector); /// /// 执行SQL查询,返回 T1 实体所有字段的记录,记录不存在时返回 Count 为 0 的列表 /// 注意: diff --git a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs index 5f843cf7..5f3a6a88 100644 --- a/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs +++ b/FreeSql/Internal/CommonProvider/SelectProvider/Select0Provider.cs @@ -479,6 +479,39 @@ namespace FreeSql.Internal.CommonProvider this.ToListChunkPrivate(size, done, includeNestedMembers == false ? this.GetAllFieldExpressionTreeLevel2() : this.GetAllFieldExpressionTreeLevelAll(), null); } #endregion + public Dictionary ToDictionary(Func keySelector) => ToDictionary(keySelector, a => a); + public Dictionary ToDictionary(Func keySelector, Func valueSelector) + { + if (keySelector == null) throw new ArgumentNullException(nameof(keySelector)); + if (valueSelector == null) throw new ArgumentNullException(nameof(valueSelector)); + var af = this.GetAllFieldExpressionTreeLevel2(); + var sql = this.ToSql(af.Field); + var dbParms = _params.ToArray(); + var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + var ret = new Dictionary(); + Exception exception = null; + try + { + _orm.Ado.ExecuteReader(_connection, _transaction, dr => + { + var item = af.Read(_orm, dr); + ret.Add(keySelector(item), valueSelector(item)); + }, CommandType.Text, sql, dbParms); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + if (typeof(TValue) == typeof(T1)) _trackToList?.Invoke(ret.Values); + return ret; + } public virtual List ToList(bool includeNestedMembers = false) { if (_selectExpression != null) return this.InternalToList(_selectExpression); @@ -1251,6 +1284,40 @@ namespace FreeSql.Internal.CommonProvider return ToListAfPrivateAsync(sql, af, otherData); } + public Task> ToDictionaryAsync(Func keySelector) => ToDictionaryAsync(keySelector, a => a); + async public Task> ToDictionaryAsync(Func keySelector, Func valueSelector) + { + if (keySelector == null) throw new ArgumentNullException(nameof(keySelector)); + if (valueSelector == null) throw new ArgumentNullException(nameof(valueSelector)); + var af = this.GetAllFieldExpressionTreeLevel2(); + var sql = this.ToSql(af.Field); + var dbParms = _params.ToArray(); + var before = new Aop.CurdBeforeEventArgs(_tables[0].Table.Type, _tables[0].Table, Aop.CurdType.Select, sql, dbParms); + _orm.Aop.CurdBeforeHandler?.Invoke(this, before); + var ret = new Dictionary(); + Exception exception = null; + try + { + await _orm.Ado.ExecuteReaderAsync(_connection, _transaction, dr => + { + var item = af.Read(_orm, dr); + ret.Add(keySelector(item), valueSelector(item)); + return Task.FromResult(false); + }, CommandType.Text, sql, dbParms); + } + catch (Exception ex) + { + exception = ex; + throw ex; + } + finally + { + var after = new Aop.CurdAfterEventArgs(before, exception, ret); + _orm.Aop.CurdAfterHandler?.Invoke(this, after); + } + if (typeof(TValue) == typeof(T1)) _trackToList?.Invoke(ret.Values); + return ret; + } public virtual Task> ToListAsync(bool includeNestedMembers = false) { if (_selectExpression != null) return this.InternalToListAsync(_selectExpression);