diff --git a/.github/workflows/docfx.yml b/.github/workflows/docfx.yml index 9ecb6663..0ff00767 100644 --- a/.github/workflows/docfx.yml +++ b/.github/workflows/docfx.yml @@ -3,48 +3,30 @@ name: .NET Core Deploy Docfx on: push: branches: [master] - pull_request: - branches: [master] jobs: - build: - runs-on: ubuntu-latest - - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Setup .NET Core - uses: actions/setup-dotnet@v1 - with: - dotnet-version: 5.0.202 - - name: Exclude example projects - run: dotnet sln FreeSql.sln remove Examples/**/*.csproj FreeSql.Tests/**/*.csproj - - name: Install dependencies - run: dotnet restore - - name: Build solution - run: dotnet build --configuration Release --no-restore - generate-docs: runs-on: windows-latest - needs: build steps: - name: Checkout uses: actions/checkout@v2 - name: Setup .NET Core uses: actions/setup-dotnet@v1 - with: - dotnet-version: 5.0.202 + with: + dotnet-version: 5.0.x - name: Remove Examples run: dotnet sln FreeSql.sln remove (ls -r Examples/**/*.csproj) - name: Remove FreeSql.Tests run: dotnet sln FreeSql.sln remove (ls -r FreeSql.Tests/**/*.csproj) - name: Install dependencies run: dotnet restore + - name: Build solution + run: dotnet build --configuration Release --no-restore - name: Setup DocFX uses: crazy-max/ghaction-chocolatey@v1 with: - args: install docfx --version 2.56.7 + args: install docfx - name: DocFX Build working-directory: docs run: docfx docfx.json diff --git a/FreeSql.Tests/FreeSql.Tests/Issues/803.cs b/FreeSql.Tests/FreeSql.Tests/Issues/803.cs new file mode 100644 index 00000000..dc98e8e2 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Issues/803.cs @@ -0,0 +1,66 @@ +using FreeSql.DataAnnotations; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Data; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Linq; +using Xunit; + +namespace FreeSql.Tests.Issues +{ + public class _803 + { + [Table(Name = "crm_sale_order")] + class crm_sale_order + { + [Column(IsPrimary = true, IsIdentity = true)] + public int id { get; set; } + public string name { get; set; } + + public int tag_count { get; set; } + public int gateway_count { get; set; } + + [JsonProperty, Column(DbType = "varchar(30)", CanUpdate = false)] + public string create_by { get; set; } = string.Empty; + + [JsonProperty, Column(DbType = "datetime", CanUpdate = false)] + public DateTime create_time { get; set; } + } + + [Fact] + public void IgnoreColumnsTest() + { + IFreeSql fsql = g.mysql; + var dto = new crm_sale_order + { + name = "name", + create_by = "create_by", + create_time = DateTime.Now + }; + fsql.Insert().AppendData(dto).ExecuteAffrows(); + + var crmDto = fsql.Select().OrderByDescending(r => r.id).First(); + + crmDto.name = "name" + new Random().Next(100); + crmDto.tag_count = new Random().Next(100); + crmDto.gateway_count = new Random().Next(100); + crmDto.create_by = "create_by" + new Random().Next(100); + crmDto.create_time = DateTime.Now.AddMinutes(10); + + fsql.Update().SetSource(crmDto).IgnoreColumns(s => new { s.tag_count, s.gateway_count }).ExecuteAffrows(); + + var updateDto = fsql.Select().OrderByDescending(r => r.id).First(); + + Assert.Equal(updateDto.tag_count, dto.tag_count); + Assert.Equal(updateDto.gateway_count, dto.gateway_count); + Assert.Equal(updateDto.create_time.ToString("g"), dto.create_time.ToString("g")); + Assert.Equal(updateDto.create_by, dto.create_by); + + Assert.Equal(updateDto.name, crmDto.name); + + } + } +} diff --git a/FreeSql.Tests/FreeSql.Tests/Issues/804.cs b/FreeSql.Tests/FreeSql.Tests/Issues/804.cs new file mode 100644 index 00000000..3bab23f5 --- /dev/null +++ b/FreeSql.Tests/FreeSql.Tests/Issues/804.cs @@ -0,0 +1,117 @@ +using FreeSql.DataAnnotations; +using System; +using System.Linq; +using Xunit; + +namespace FreeSql.Tests.Issues +{ + public class _804 + { + [Table(Name = "Users_804")] + class Users + { + [Column(IsPrimary = true, IsIdentity = true)] + public int Id { get; set; } + public string UserName { get; set; } + + public DateTime CreateTime { get; set; } + } + + [Fact] + public void TestYear() + { + var fsql = g.sqlite; + fsql.Delete().Where("1=1").ExecuteAffrows(); + fsql.Insert().AppendData(new Users { UserName = "admn", CreateTime = DateTime.Now }).ExecuteAffrows(); + int year = DateTime.Now.Year; + string strYear = year.ToString(); + //这个都能查到数据 + var d1 = fsql.Select().Where(r => r.CreateTime.Year == Convert.ToInt32(strYear)).ToList(); + /* + SELECT a."Id", a."UserName", a."CreateTime" +FROM "Users_677" a +WHERE (strftime('%Y',a."CreateTime") = cast('2021' as smallint)) + */ + var d2 = fsql.Select().Where(r => r.CreateTime.Year == DateTime.Now.Year).ToList(); + var d3 = fsql.Select().Where(r => r.CreateTime.Year.ToString() == strYear).ToList(); + var d4 = fsql.Select().Where(r => Convert.ToInt32(r.CreateTime.Year) == year).ToList(); + + //只有这种方式在sqlite下无法查到数据 + var d5 = fsql.Select().Where(r => r.CreateTime.Year == year).ToList(); + /* +SELECT a."Id", a."UserName", a."CreateTime" +FROM "Users_677" a +WHERE (strftime('%Y',a."CreateTime") = 2021) + + */ + Assert.Single(d1); + Assert.Single(d2); + Assert.Single(d3); + Assert.Single(d4); + Assert.Single(d5); + + } + + + [Fact] + public void TestMonthAndData() + { + var fsql = g.sqlite; + fsql.Delete().Where("1=1").ExecuteAffrows(); + fsql.Insert().AppendData(new Users { UserName = "admin", CreateTime = DateTime.Now }).ExecuteAffrows(); + + var year = DateTime.Now.Year; + var month = DateTime.Now.Month; + + var d3 = fsql.Select().ToList(r => new + { + r.CreateTime, + r.CreateTime.Date, + r.CreateTime.TimeOfDay, + r.CreateTime.DayOfWeek, + r.CreateTime.Day, + r.CreateTime.DayOfYear, + r.CreateTime.Month, + r.CreateTime.Year, + r.CreateTime.Hour, + r.CreateTime.Minute, + r.CreateTime.Second, + r.CreateTime.Millisecond, + r.CreateTime.Ticks, + }); + + Assert.Single(d3); + + var d3_first = d3.First(); + + Assert.Equal(d3_first.Date, d3_first.CreateTime.Date); + //精度到毫秒 + Assert.Equal((long)(d3_first.TimeOfDay.TotalMilliseconds + 0.5), (long)(d3_first.CreateTime.TimeOfDay.TotalMilliseconds + 0.5)); + Assert.Equal(d3_first.DayOfWeek, d3_first.CreateTime.DayOfWeek); + Assert.Equal(d3_first.Day, d3_first.CreateTime.Day); + Assert.Equal(d3_first.DayOfYear, d3_first.CreateTime.DayOfYear); + Assert.Equal(d3_first.Month, d3_first.CreateTime.Month); + Assert.Equal(d3_first.Year, d3_first.CreateTime.Year); + Assert.Equal(d3_first.Hour, d3_first.CreateTime.Hour); + Assert.Equal(d3_first.Minute, d3_first.CreateTime.Minute); + Assert.Equal(d3_first.Second, d3_first.CreateTime.Second); + Assert.Equal(d3_first.Millisecond, d3_first.CreateTime.Millisecond); + //精度到毫秒 ,四舍五入 + Assert.Equal((long)(d3_first.Ticks / 10000.0 + 0.5), (long)(d3_first.CreateTime.Ticks / 10000.0 + 0.5)); + + + string strMonth = month.ToString(); + var dmonth1 = fsql.Select().Where(r => r.CreateTime.Month.ToString() == strMonth).ToList(); + + + var d1 = fsql.Select().Where(r => r.CreateTime.Month == month).ToList(); + var d2 = fsql.Select().Where(r => r.CreateTime.Year == year).ToList(); + var d5 = fsql.Select().Where(r => r.CreateTime.Year == 2021).ToList(); + + Assert.Single(dmonth1); + Assert.Single(d1); + Assert.Single(d1); + Assert.Single(d5); + } + } +} diff --git a/FreeSql/Internal/CommonProvider/UpdateProvider.cs b/FreeSql/Internal/CommonProvider/UpdateProvider.cs index e59bc898..cb64f283 100644 --- a/FreeSql/Internal/CommonProvider/UpdateProvider.cs +++ b/FreeSql/Internal/CommonProvider/UpdateProvider.cs @@ -351,8 +351,9 @@ namespace FreeSql.Internal.CommonProvider { var cols = columns.Distinct().ToDictionary(a => a); _ignore.Clear(); + IgnoreCanUpdate(); foreach (var col in _table.Columns.Values) - if (cols.ContainsKey(col.Attribute.Name) == true || cols.ContainsKey(col.CsName) == true) + if (!_ignore.ContainsKey(col.Attribute.Name) && (cols.ContainsKey(col.Attribute.Name) == true || cols.ContainsKey(col.CsName) == true)) _ignore.Add(col.Attribute.Name, true); return this; } diff --git a/FreeSql/Internal/Model/DynamicFilterInfo.cs b/FreeSql/Internal/Model/DynamicFilterInfo.cs index 64adb791..060d772b 100644 --- a/FreeSql/Internal/Model/DynamicFilterInfo.cs +++ b/FreeSql/Internal/Model/DynamicFilterInfo.cs @@ -13,6 +13,7 @@ namespace FreeSql.Internal.Model /// /// 动态过滤条件 /// + [Serializable] public class DynamicFilterInfo { /// diff --git a/Providers/FreeSql.Provider.Dameng/DamengUtils.cs b/Providers/FreeSql.Provider.Dameng/DamengUtils.cs index cdf77206..7376f7c4 100644 --- a/Providers/FreeSql.Provider.Dameng/DamengUtils.cs +++ b/Providers/FreeSql.Provider.Dameng/DamengUtils.cs @@ -23,14 +23,21 @@ namespace FreeSql.Dameng { case DmDbType.Bit: if (value == null) value = null; - else value = (bool) value == true ? 1 : 0; + else value = (bool)value == true ? 1 : 0; dbtype = DmDbType.Int32; break; - + case DmDbType.Char: case DmDbType.VarChar: case DmDbType.Text: - value = string.Concat(value); + if (value == null) + { + value = (string)null; + } + else + { + value = string.Concat(value); + } break; } var ret = new DmParameter { ParameterName = QuoteParamterName(parameterName), DmSqlType = dbtype, Value = value }; @@ -56,7 +63,14 @@ namespace FreeSql.Dameng case DmDbType.Char: case DmDbType.VarChar: case DmDbType.Text: - value = string.Concat(value); + if (value == null) + { + value = (string)null; + } + else + { + value = string.Concat(value); + } break; } } diff --git a/Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs b/Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs index eebdb488..8f3c1710 100644 --- a/Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs +++ b/Providers/FreeSql.Provider.Sqlite/SqliteExpression.cs @@ -1,10 +1,10 @@ -using System; +using FreeSql.Internal; +using System; using System.Collections; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Text.RegularExpressions; -using FreeSql.Internal; namespace FreeSql.Sqlite { @@ -201,17 +201,17 @@ namespace FreeSql.Sqlite switch (exp.Member.Name) { case "Date": return $"date({left})"; - case "TimeOfDay": return $"strftime('%s',{left})"; - case "DayOfWeek": return $"strftime('%w',{left})"; - case "Day": return $"strftime('%d',{left})"; - case "DayOfYear": return $"strftime('%j',{left})"; - case "Month": return $"strftime('%m',{left})"; - case "Year": return $"strftime('%Y',{left})"; - case "Hour": return $"strftime('%H',{left})"; - case "Minute": return $"strftime('%M',{left})"; - case "Second": return $"strftime('%S',{left})"; - case "Millisecond": return $"(strftime('%f',{left})-strftime('%S',{left}))"; - case "Ticks": return $"(strftime('%s',{left})*10000000+621355968000000000)"; + case "TimeOfDay": return $"strftime('%H:%M:%f',{left})"; + case "DayOfWeek": return $"CAST(strftime('%w',{left}) AS INTEGER) "; + case "Day": return $"CAST(strftime('%d',{left}) AS INTEGER) "; + case "DayOfYear": return $"CAST(strftime('%j',{left}) AS INTEGER) "; + case "Month": return $"CAST(strftime('%m',{left}) AS INTEGER) "; + case "Year": return $"CAST(strftime('%Y',{left}) AS INTEGER) "; + case "Hour": return $"CAST(strftime('%H',{left}) AS INTEGER) "; + case "Minute": return $"CAST(strftime('%M',{left}) AS INTEGER) "; + case "Second": return $"CAST(strftime('%S',{left}) AS INTEGER) "; + case "Millisecond": return $"CAST(strftime('%f',{left})*1000.0%1000.0 AS INTEGER)"; + case "Ticks": return $"CAST(((strftime( '%J',{left}) - 1721425.5 ) * {TimeSpan.TicksPerDay} ) AS INTEGER ) ";//精度到毫秒 } return null; }