diff --git a/Build/linq2db.Default.props b/Build/linq2db.Default.props index ac28b27..3afa1ab 100644 --- a/Build/linq2db.Default.props +++ b/Build/linq2db.Default.props @@ -1,6 +1,6 @@  - 3.10.0 + 3.10.1 Svyatoslav Danyliv, Igor Tkachev, Dmitry Lukashenko, Ilya Chudin Linq to DB diff --git a/Source/LinqToDB.EntityFrameworkCore/LinqToDBExtensionsAdapter.cs b/Source/LinqToDB.EntityFrameworkCore/LinqToDBExtensionsAdapter.cs index a40260d..7e4d5db 100644 --- a/Source/LinqToDB.EntityFrameworkCore/LinqToDBExtensionsAdapter.cs +++ b/Source/LinqToDB.EntityFrameworkCore/LinqToDBExtensionsAdapter.cs @@ -87,17 +87,21 @@ public Task FirstAsync( => EntityFrameworkQueryableExtensions.FirstAsync(source, predicate, token); /// - public Task FirstOrDefaultAsync( + public Task FirstOrDefaultAsync( IQueryable source, CancellationToken token) +#pragma warning disable CS8619 // Nullability of reference types in value doesn't match target type. => EntityFrameworkQueryableExtensions.FirstOrDefaultAsync(source, token); +#pragma warning restore CS8619 // Nullability of reference types in value doesn't match target type. /// - public Task FirstOrDefaultAsync( + public Task FirstOrDefaultAsync( IQueryable source, Expression> predicate, CancellationToken token) +#pragma warning disable CS8619 // Nullability of reference types in value doesn't match target type. => EntityFrameworkQueryableExtensions.FirstOrDefaultAsync(source, predicate, token); +#pragma warning restore CS8619 // Nullability of reference types in value doesn't match target type. /// public Task SingleAsync( @@ -113,17 +117,21 @@ public Task SingleAsync( => EntityFrameworkQueryableExtensions.SingleAsync(source, predicate, token); /// - public Task SingleOrDefaultAsync( + public Task SingleOrDefaultAsync( IQueryable source, CancellationToken token) +#pragma warning disable CS8619 // Nullability of reference types in value doesn't match target type. => EntityFrameworkQueryableExtensions.SingleOrDefaultAsync(source, token); +#pragma warning restore CS8619 // Nullability of reference types in value doesn't match target type. /// - public Task SingleOrDefaultAsync( + public Task SingleOrDefaultAsync( IQueryable source, Expression> predicate, CancellationToken token) +#pragma warning disable CS8619 // Nullability of reference types in value doesn't match target type. => EntityFrameworkQueryableExtensions.SingleOrDefaultAsync(source, predicate, token); +#pragma warning restore CS8619 // Nullability of reference types in value doesn't match target type. /// public Task ContainsAsync( diff --git a/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFExtensions.Async.cs b/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFExtensions.Async.cs index f80e2af..302eef8 100644 --- a/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFExtensions.Async.cs +++ b/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFExtensions.Async.cs @@ -76,13 +76,13 @@ public static Task FirstAsyncLinqToDB( => AsyncExtensions.FirstAsync(source.ToLinqToDB(), predicate, token); /// - public static Task FirstOrDefaultAsyncLinqToDB( + public static Task FirstOrDefaultAsyncLinqToDB( this IQueryable source, CancellationToken token = default) => AsyncExtensions.FirstOrDefaultAsync(source.ToLinqToDB(), token); /// - public static Task FirstOrDefaultAsyncLinqToDB( + public static Task FirstOrDefaultAsyncLinqToDB( this IQueryable source, Expression> predicate, CancellationToken token = default) @@ -102,13 +102,13 @@ public static Task SingleAsyncLinqToDB( => AsyncExtensions.SingleAsync(source.ToLinqToDB(), predicate, token); /// - public static Task SingleOrDefaultAsyncLinqToDB( + public static Task SingleOrDefaultAsyncLinqToDB( this IQueryable source, CancellationToken token = default) => AsyncExtensions.SingleOrDefaultAsync(source.ToLinqToDB(), token); /// - public static Task SingleOrDefaultAsyncLinqToDB( + public static Task SingleOrDefaultAsyncLinqToDB( this IQueryable source, Expression> predicate, CancellationToken token = default) diff --git a/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFTools.ContextExtensions.cs b/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFTools.ContextExtensions.cs index c8a5c7c..bff79d3 100644 --- a/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFTools.ContextExtensions.cs +++ b/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFTools.ContextExtensions.cs @@ -233,6 +233,7 @@ public static async Task BulkCopyAsync( [LinqTunnel] [Pure] public static IValueInsertable Into(this DbContext context, ITable target) + where T: notnull { if (context == null) throw new ArgumentNullException(nameof(context)); if (target == null) throw new ArgumentNullException(nameof(target)); diff --git a/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsImplDefault.cs b/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsImplDefault.cs index c79ba96..b60cbfc 100644 --- a/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsImplDefault.cs +++ b/Source/LinqToDB.EntityFrameworkCore/LinqToDBForEFToolsImplDefault.cs @@ -331,7 +331,7 @@ protected virtual IDataProvider CreateSqlServerProvider(SqlServerVersion version { providerName = "Microsoft.Data.SqlClient"; - return DataConnection.GetDataProvider(providerName, connectionString)!; + return DataConnection.GetDataProvider(providerName, connectionString!)!; } switch (version) @@ -364,7 +364,7 @@ protected virtual IDataProvider CreateSqlServerProvider(SqlServerVersion version protected virtual IDataProvider CreatePostgreSqlProvider(PostgreSQLVersion version, string? connectionString) { if (!string.IsNullOrEmpty(connectionString)) - return DataConnection.GetDataProvider(ProviderName.PostgreSQL, connectionString)!; + return DataConnection.GetDataProvider(ProviderName.PostgreSQL, connectionString!)!; string providerName; switch (version) @@ -450,6 +450,10 @@ public virtual void DefineConvertors( if (modelType.IsEnum) continue; + // skipping arrays + if (modelType.IsArray) + continue; + MapEFCoreType(modelType); if (modelType.IsValueType && !typeof(Nullable<>).IsSameOrParentOf(modelType)) MapEFCoreType(typeof(Nullable<>).MakeGenericType(modelType)); diff --git a/Source/LinqToDB.EntityFrameworkCore/linq2db.EntityFrameworkCore.csproj b/Source/LinqToDB.EntityFrameworkCore/linq2db.EntityFrameworkCore.csproj index b2f6cce..0c5d2f2 100644 --- a/Source/LinqToDB.EntityFrameworkCore/linq2db.EntityFrameworkCore.csproj +++ b/Source/LinqToDB.EntityFrameworkCore/linq2db.EntityFrameworkCore.csproj @@ -16,9 +16,19 @@ latest + + portable + true + true + + + + all + runtime; build; native; contentfiles; analyzers + diff --git a/Tests/LinqToDB.EntityFrameworkCore.BaseTests/LinqToDB.EntityFrameworkCore.BaseTests.csproj b/Tests/LinqToDB.EntityFrameworkCore.BaseTests/LinqToDB.EntityFrameworkCore.BaseTests.csproj index 002be19..bf604a6 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.BaseTests/LinqToDB.EntityFrameworkCore.BaseTests.csproj +++ b/Tests/LinqToDB.EntityFrameworkCore.BaseTests/LinqToDB.EntityFrameworkCore.BaseTests.csproj @@ -10,6 +10,7 @@ + diff --git a/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Logging/TestLogger.cs b/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Logging/TestLogger.cs index 6879d86..d637fbc 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Logging/TestLogger.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.BaseTests/Logging/TestLogger.cs @@ -13,7 +13,9 @@ internal class TestLogger : ILogger private static readonly string _newLineWithMessagePadding; // ConsoleColor does not have a value to specify the 'Default' color +#pragma warning disable 649 private readonly ConsoleColor? DefaultConsoleColor; +#pragma warning restore 649 private readonly string _name; diff --git a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/NpgSqlEntities/EntityWithArrays.cs b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/NpgSqlEntities/EntityWithArrays.cs new file mode 100644 index 0000000..33f0b2a --- /dev/null +++ b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/NpgSqlEntities/EntityWithArrays.cs @@ -0,0 +1,13 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace LinqToDB.EntityFrameworkCore.PostgreSQL.Tests.Models.NpgSqlEntities +{ + public class EntityWithArrays + { + [Key] + public int Id { get; set; } + + public Guid[] Guids { get; set; } = null!; + } +} diff --git a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/NpgSqlEntities/NpgSqlEnititesContext.cs b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/NpgSqlEntities/NpgSqlEnititesContext.cs index c02c2d4..45e90b9 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/NpgSqlEntities/NpgSqlEnititesContext.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/Models/NpgSqlEntities/NpgSqlEnititesContext.cs @@ -20,9 +20,14 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) entity.HasNoKey(); entity.ToView("EventsView", "views"); }); + + modelBuilder.Entity(entity => + { + }); } public virtual DbSet Events { get; set; } = null!; + public virtual DbSet EntityWithArrays { get; set; } = null!; } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/NpgSqlTests.cs b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/NpgSqlTests.cs index 58fda4d..ef7d1ef 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/NpgSqlTests.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/NpgSqlTests.cs @@ -1,6 +1,8 @@ using System; using System.Linq; +using FluentAssertions; using LinqToDB.Data; +using LinqToDB.DataProvider.PostgreSQL; using LinqToDB.EntityFrameworkCore.BaseTests; using LinqToDB.EntityFrameworkCore.PostgreSQL.Tests.Models.NpgSqlEntities; using Microsoft.EntityFrameworkCore; @@ -29,11 +31,13 @@ public NpgSqlTests() _options = optionsBuilder.Options; } - private NpgSqlEnititesContext CreateNpgSqlExntitiesContext() + private NpgSqlEnititesContext CreateNpgSqlEntitiesContext() { var ctx = new NpgSqlEnititesContext(_options); ctx.Database.EnsureDeleted(); ctx.Database.EnsureCreated(); + ctx.Database.ExecuteSqlRaw("create schema \"views\""); + ctx.Database.ExecuteSqlRaw("create view \"views\".\"EventsView\" as select \"Name\" from \"Events\""); return ctx; } @@ -41,7 +45,7 @@ private NpgSqlEnititesContext CreateNpgSqlExntitiesContext() [Test] public void TestFunctionsMapping() { - using (var db = CreateNpgSqlExntitiesContext()) + using (var db = CreateNpgSqlEntitiesContext()) { var date = DateTime.UtcNow; @@ -54,6 +58,35 @@ public void TestFunctionsMapping() } } - + [Test] + public void TestViewMapping() + { + using (var db = CreateNpgSqlEntitiesContext()) + { + var query = db.Set().Where(e => + e.Name.StartsWith("any")); + + var efResult = query.ToArray(); + var l2dbResult = query.ToLinqToDB().ToArray(); + } + } + + [Test] + public void TestArray() + { + using (var db = CreateNpgSqlEntitiesContext()) + { + var guids = new Guid[] { Guid.Parse("271425b1-ebe8-400d-b71d-a6e47a460ae3"), + Guid.Parse("b75de94e-6d7b-4c70-bfa1-f8639a6a5b35") }; + + var query = + from m in db.EntityWithArrays.ToLinqToDBTable() + where Sql.Ext.PostgreSQL().Overlaps(m.Guids, guids) + select m; + + query.Invoking(q => q.ToArray()).Should().NotThrow(); + } + } + } } diff --git a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/AAA.cs b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/AAA.cs index 475ffce..756370e 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/AAA.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.PostgreSQL.Tests/SampleTests/AAA.cs @@ -1,6 +1,9 @@ using System; using System.Threading.Tasks; +#pragma warning disable 8604 +#pragma warning disable CS8625 + namespace LinqToDB.EntityFrameworkCore.PostgreSQL.Tests.SampleTests { public class Unit diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/IssueTests.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/IssueTests.cs index 2afa3d8..27c0815 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/IssueTests.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/IssueTests.cs @@ -9,7 +9,7 @@ namespace LinqToDB.EntityFrameworkCore.SqlServer.Tests [TestFixture] public class IssueTests : TestsBase { - private DbContextOptions? _options; + private DbContextOptions _options = null!; private bool _created; public IssueTests() diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/IssueModel/IssueContext.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/IssueModel/IssueContext.cs index 76d8d99..e8dee5c 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/IssueModel/IssueContext.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/Models/IssueModel/IssueContext.cs @@ -43,7 +43,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder .Entity() .HasOne(p => p.Assessment) - .WithOne(pa => pa.Patent) + .WithOne(pa => pa!.Patent) .HasForeignKey(pa => pa.PatentId) .OnDelete(DeleteBehavior.Restrict); diff --git a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ToolsTests.cs b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ToolsTests.cs index 6e55836..d50e25b 100644 --- a/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ToolsTests.cs +++ b/Tests/LinqToDB.EntityFrameworkCore.SqlServer.Tests/ToolsTests.cs @@ -669,7 +669,7 @@ public async Task TestSetUpdate([Values(true, false)] bool enableFilter) { using (var ctx = CreateContext(enableFilter)) { - var customer = await ctx.Customers.FirstOrDefaultAsync(); + var customer = await ctx.Customers.FirstAsync(); var updatable = ctx.Customers.Where(c => c.CustomerId == customer.CustomerId) .Set(c => c.CompanyName, customer.CompanyName); diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 49f91c2..fc8d972 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,8 +1,8 @@ variables: solution: 'linq2db.EFCore.sln' build_configuration: 'Release' - assemblyVersion: 3.10.0 - nugetVersion: 3.10.0 + assemblyVersion: 3.10.1 + nugetVersion: 3.10.1 artifact_nugets: 'nugets' # build on commits to important branches (master + release branches): @@ -44,12 +44,12 @@ stages: inputs: solution: '$(solution)' configuration: '$(build_configuration)' - msbuildArguments: '/t:Restore;Rebuild -m' + msbuildArguments: '/t:Restore;Rebuild -m /p:ContinuousIntegrationBuild=true' displayName: Build Solution - powershell: echo "##vso[task.setvariable variable=packageVersion]$(packageVersion)-rc.$(Build.BuildId)" - condition: ne(variables['Build.SourceBranchName'], 'release.3') displayName: Set nuget RC version for non-release branch + condition: and(succeeded(), eq(variables['Build.SourceBranchName'], 'version3')) - task: PowerShell@2 inputs: @@ -57,24 +57,35 @@ stages: workingDirectory: '$(Build.SourcesDirectory)' arguments: -path $(Build.SourcesDirectory)/NuGet/linq2db.EntityFrameworkCore.nuspec -version $(packageVersion) -branch $(Build.SourceBranchName) displayName: Generate nuspec + condition: and(succeeded(), or(eq(variables['Build.SourceBranchName'], 'release.3'), eq(variables['Build.SourceBranchName'], 'version3'))) - task: NuGetToolInstaller@0 inputs: versionSpec: '5.x' workingDirectory: $(Build.SourcesDirectory)/NuGet displayName: Install nuget + condition: and(succeeded(), or(eq(variables['Build.SourceBranchName'], 'release.3'), eq(variables['Build.SourceBranchName'], 'version3'))) - task: CmdLine@2 inputs: script: 'nuget Pack linq2db.EntityFrameworkCore.nuspec -OutputDirectory built' workingDirectory: $(Build.SourcesDirectory)/NuGet - displayName: Build nuget + displayName: Build nuget (azure artifacts) + condition: and(succeeded(), eq(variables['Build.SourceBranchName'], 'version3')) + + - task: CmdLine@2 + inputs: + script: 'nuget Pack linq2db.EntityFrameworkCore.nuspec -OutputDirectory built -Symbols -SymbolPackageFormat snupkg' + workingDirectory: $(Build.SourcesDirectory)/NuGet + displayName: Build nuget (nuget.org) + condition: and(succeeded(), eq(variables['Build.SourceBranchName'], 'release.3')) - task: PublishBuildArtifacts@1 inputs: pathToPublish: '$(Build.SourcesDirectory)/NuGet/built' artifactName: '$(artifact_nugets)' displayName: Publish nugets to artifacts + condition: and(succeeded(), or(eq(variables['Build.SourceBranchName'], 'release.3'), eq(variables['Build.SourceBranchName'], 'version3'))) - task: NuGetCommand@2 inputs: