diff --git a/All.sln b/All.sln index a303553dda8..7020ff3db50 100644 --- a/All.sln +++ b/All.sln @@ -2,7 +2,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.0.31521.260 -MinimumVisualStudioVersion = 16.0.28418.106 +MinimumVisualStudioVersion = 17.0.31521.260 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B9E4CC99-199C-4E3B-9EC5-D1FDFCD6C27B}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig diff --git a/src/EFCore.SqlServer/Update/Internal/SqlServerUpdateSqlGenerator.cs b/src/EFCore.SqlServer/Update/Internal/SqlServerUpdateSqlGenerator.cs index 2261098cd1b..742244fcd03 100644 --- a/src/EFCore.SqlServer/Update/Internal/SqlServerUpdateSqlGenerator.cs +++ b/src/EFCore.SqlServer/Update/Internal/SqlServerUpdateSqlGenerator.cs @@ -65,7 +65,7 @@ public virtual ResultSetMapping AppendBulkInsertOperation( modificationCommands[0], modificationCommands[0].ColumnModifications.Where(o => o.IsKey).ToList(), modificationCommands[0].ColumnModifications.Where(o => o.IsRead).ToList(), - 0); + commandPosition); } var readOperations = modificationCommands[0].ColumnModifications.Where(o => o.IsRead).ToList(); diff --git a/test/EFCore.SqlServer.FunctionalTests/SqlServerEndToEndTest.cs b/test/EFCore.SqlServer.FunctionalTests/SqlServerEndToEndTest.cs index 2f4add8abb0..ee455da0fab 100644 --- a/test/EFCore.SqlServer.FunctionalTests/SqlServerEndToEndTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/SqlServerEndToEndTest.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.TestUtilities; using Xunit; @@ -873,6 +874,193 @@ public void Can_replace_identifying_FK_entity_with_many_to_many() } } + [ConditionalTheory] + [MemberData( + nameof(DataGenerator.GetCombinations), + new object[] { 0, 1, 2, 3, 4 }, + 2, + MemberType = typeof(DataGenerator))] + public void Can_insert_entities_with_generated_PKs(int studentCount, int courseCount) + { + var students = new Student[] + { + new Student{FirstMidName="Carson",LastName="Alexander",EnrollmentDate=DateTime.Parse("2019-09-01")}, + new Student{FirstMidName="Meredith",LastName="Alonso",EnrollmentDate=DateTime.Parse("2017-09-01")}, + new Student{FirstMidName="Arturo",LastName="Anand",EnrollmentDate=DateTime.Parse("2018-09-01")}, + new Student{FirstMidName="Gytis",LastName="Barzdukas",EnrollmentDate=DateTime.Parse("2017-09-01")}, + new Student{FirstMidName="Yan",LastName="Li",EnrollmentDate=DateTime.Parse("2017-09-01")}, + new Student{FirstMidName="Peggy",LastName="Justice",EnrollmentDate=DateTime.Parse("2016-09-01")}, + new Student{FirstMidName="Laura",LastName="Norman",EnrollmentDate=DateTime.Parse("2018-09-01")}, + new Student{FirstMidName="Nino",LastName="Olivetto",EnrollmentDate=DateTime.Parse("2019-09-01")} + }; + + var courses = new Course[] + { + new Course{Title="Chemistry",Credits=3}, + new Course{Title="Microeconomics",Credits=3}, + new Course{Title="Macroeconomics",Credits=3}, + new Course{Title="Calculus",Credits=4}, + new Course{Title="Trigonometry",Credits=4}, + new Course{Title="Composition",Credits=3}, + new Course{Title="Literature",Credits=4} + }; + + using var testDatabase = SqlServerTestStore.CreateInitialized(DatabaseName); + var options = Fixture.CreateOptions(testDatabase); + + using (var context = new UniversityContext(options)) + { + context.Database.EnsureCreatedResiliently(); + for (var i = 0; i < studentCount; i++) + { + context.Students.Add(students[i]); + } + for (var i = 0; i < courseCount; i++) + { + context.Courses.Add(courses[i]); + } + + context.SaveChanges(); + } + + using (var context = new UniversityContext(options)) + { + Assert.Equal(studentCount, context.Students.Count()); + Assert.Equal(courseCount, context.Courses.Count()); + } + } + + public class Course + { + public Guid Id { get; set; } + + public string Title { get; set; } = string.Empty; + + public int Credits { get; set; } + + public virtual ICollection Enrollments { get; set; } = new List(); + + public byte[] RowVersion { get; set; } = Array.Empty(); + } + + public class Student + { + public Guid Id { get; set; } + + public string LastName { get; set; } = string.Empty; + + public string FirstMidName { get; set; } = string.Empty; + + public DateTime EnrollmentDate { get; set; } + + public virtual ICollection Enrollments { get; } = new List(); + + public byte[] RowVersion { get; set; } = Array.Empty(); + } + + public enum Grade + { + A, B, C, D, F + } + + public class Enrollment + { + public Guid Id { get; set; } + + public Guid CourseId { get; set; } + + public Guid StudentId { get; set; } + + public Grade? Grade { get; set; } + + public virtual Course Course { get; set; } = new(); + + public virtual Student Student { get; set; } = new(); + + public byte[] RowVersion { get; set; } = Array.Empty(); + } + + private class UniversityContext : DbContext + { + public UniversityContext(DbContextOptions options) + : base(options) + { + } + + public DbSet Students { get; set; } + public DbSet Courses { get; set; } + public DbSet Enrollments { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity(builder => + { + builder.ToTable("Courses"); + + builder.HasKey(x => x.Id); + + builder.Property(x => x.Id) + .ValueGeneratedOnAdd() + .HasDefaultValueSql("NEWSEQUENTIALID()"); + + builder.Property(x => x.Title) + .IsRequired() + .HasMaxLength(50); + + builder.Property(x => x.RowVersion) + .IsRowVersion(); + }); + + modelBuilder.Entity(builder => + { + builder.ToTable("Students"); + + builder.HasKey(x => x.Id); + + builder.Property(x => x.Id) + .ValueGeneratedOnAdd() + .HasDefaultValueSql("NEWSEQUENTIALID()"); + + builder.Property(x => x.LastName) + .IsRequired() + .HasMaxLength(50); + + builder.Property(x => x.FirstMidName) + .IsRequired() + .HasMaxLength(50); + + builder.Property(x => x.RowVersion) + .IsRowVersion(); + }); + + modelBuilder.Entity(builder => + { + builder.ToTable("Enrollments"); + + builder.HasKey(x => x.Id); + + builder.Property(x => x.Id) + .ValueGeneratedOnAdd() + .HasDefaultValueSql("NEWSEQUENTIALID()"); + + builder.Property(x => x.RowVersion) + .IsRowVersion(); + + builder.HasOne(t => t.Course) + .WithMany(t => t.Enrollments) + .HasPrincipalKey(d => d.Id) + .HasForeignKey(d => d.CourseId) + .OnDelete(DeleteBehavior.Cascade); + + builder.HasOne(t => t.Student) + .WithMany(t => t.Enrollments) + .HasPrincipalKey(d => d.Id) + .HasForeignKey(d => d.StudentId) + .OnDelete(DeleteBehavior.Cascade); + }); + } + } + private class EntityA { public int Id { get; set; }