Some updates to the migration/update sql. Main change is if we are doing an INSERT, if there is no values to be read back we don't have to follow it up with a 'SELECT @@ROWCOUNT'

pull/175/head
Christopher Jolly 2 years ago
parent c73f4a3013
commit 559cdc6d3c

@ -16,6 +16,9 @@ using Microsoft.EntityFrameworkCore.Migrations.Operations;
using Microsoft.EntityFrameworkCore.Storage;
using EntityFrameworkCore.Jet.Utilities;
using Microsoft.Extensions.DependencyInjection;
using System.Text;
using EntityFrameworkCore.Jet.Update.Internal;
using Microsoft.EntityFrameworkCore.Update;
// ReSharper disable once CheckNamespace
namespace Microsoft.EntityFrameworkCore.Migrations
@ -38,22 +41,25 @@ namespace Microsoft.EntityFrameworkCore.Migrations
private IReadOnlyList<MigrationOperation> _operations = null!;
private RelationalTypeMapping _stringTypeMapping;
private readonly ICommandBatchPreparer _commandBatchPreparer;
/// <summary>
/// Creates a new <see cref="JetMigrationsSqlGenerator" /> instance.
/// </summary>
/// <param name="dependencies"> Parameter object containing dependencies for this service. </param>
/// <param name="migrationsAnnotations"> Provider-specific Migrations annotations to use. </param>
/// <param name="options"> Provider-specific options. </param>
/// <param name="commandBatchPreparer">The command batch preparer.</param>
public JetMigrationsSqlGenerator(
[NotNull] MigrationsSqlGeneratorDependencies dependencies,
[NotNull] IMigrationsAnnotationProvider migrationsAnnotations,
[NotNull] IJetOptions options)
[NotNull] IJetOptions options,
ICommandBatchPreparer commandBatchPreparer)
: base(dependencies)
{
_migrationsAnnotations = migrationsAnnotations;
_options = options;
_stringTypeMapping = dependencies.TypeMappingSource.FindMapping(typeof(string))!;
_commandBatchPreparer = commandBatchPreparer;
}
/// <summary>
@ -704,6 +710,41 @@ namespace Microsoft.EntityFrameworkCore.Migrations
}
}
protected override void Generate(
InsertDataOperation operation,
IModel? model,
MigrationCommandListBuilder builder,
bool terminate = true)
{
var sqlBuilder = new StringBuilder();
var modificationCommands = GenerateModificationCommands(operation, model).ToList();
var updateSqlGenerator = (IJetUpdateSqlGenerator)Dependencies.UpdateSqlGenerator;
foreach (var batch in _commandBatchPreparer.CreateCommandBatches(modificationCommands, moreCommandSets: true))
{
updateSqlGenerator.AppendBulkInsertOperation(sqlBuilder, batch.ModificationCommands, commandPosition: 0);
}
if (Options.HasFlag(MigrationsSqlGenerationOptions.Idempotent))
{
builder
.Append("EXEC('")
.Append(sqlBuilder.ToString().TrimEnd('\n', '\r', ';').Replace("'", "''"))
.Append("')")
.AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator);
}
else
{
builder.Append(sqlBuilder.ToString());
}
if (terminate)
{
builder.EndCommand();
}
}
protected override void ColumnDefinition(
string? schema,
string table,

@ -30,7 +30,7 @@ namespace EntityFrameworkCore.Jet.Update.Internal
/// </summary>
public JetModificationCommandBatch(
[NotNull] ModificationCommandBatchFactoryDependencies dependencies)
: base(dependencies,1)
: base(dependencies, 1)
{
// See https://support.office.com/en-us/article/access-specifications-0cf3c66f-9cf2-4e32-9568-98c1025bb47c
// for Access specifications and limits.
@ -93,9 +93,11 @@ namespace EntityFrameworkCore.Jet.Update.Internal
ResultSetMappings.Add(resultSetMapping);
}
if (resultSetMapping != ResultSetMapping.NoResults)
// All result mappings are marked as "not last", mark the last one as "last".
if (resultSetMapping.HasFlag(ResultSetMapping.HasResultRow))
{
ResultSetMappings[^1] = ResultSetMapping.LastInResultSet;
ResultSetMappings[^1] &= ~ResultSetMapping.NotLastInResultSet;
ResultSetMappings[^1] |= ResultSetMapping.LastInResultSet;
}
}
@ -105,33 +107,39 @@ namespace EntityFrameworkCore.Jet.Update.Internal
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
protected override void AddCommand(IReadOnlyModificationCommand modificationCommand)
public override bool TryAddCommand(IReadOnlyModificationCommand modificationCommand)
{
if (modificationCommand.EntityState == EntityState.Added && modificationCommand.StoreStoredProcedure is null)
// If there are any pending bulk insert commands and the new command is incompatible with them (not an insert, insert into a
// separate table..), apply the pending commands.
if (_pendingBulkInsertCommands.Count > 0
&& (modificationCommand.EntityState != EntityState.Added
|| modificationCommand.StoreStoredProcedure is not null
|| !CanBeInsertedInSameStatement(_pendingBulkInsertCommands[0], modificationCommand)))
{
if (_pendingBulkInsertCommands.Count > 0
&& !CanBeInsertedInSameStatement(_pendingBulkInsertCommands[0], modificationCommand))
{
// The new Add command cannot be added to the pending bulk insert commands (e.g. different table).
// Write out the pending commands before starting a new pending chain.
ApplyPendingBulkInsertCommands();
_pendingBulkInsertCommands.Clear();
}
ApplyPendingBulkInsertCommands();
_pendingBulkInsertCommands.Clear();
}
return base.TryAddCommand(modificationCommand);
}
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
protected override void AddCommand(IReadOnlyModificationCommand modificationCommand)
{
// TryAddCommand above already applied any pending commands if the new command is incompatible with them.
// So if the new command is an insert, just append it to pending, otherwise do the regular add logic.
if (modificationCommand is { EntityState: EntityState.Added, StoreStoredProcedure: null })
{
_pendingBulkInsertCommands.Add(modificationCommand);
AddParameters(modificationCommand);
}
else
{
// If we have any pending bulk insert commands, write them out before the next non-Add command
if (_pendingBulkInsertCommands.Count > 0)
{
// Note that we don't care about the transactionality of the bulk insert SQL, since there's the additional non-Add
// command coming right afterwards, and so a transaction is required in any case.
ApplyPendingBulkInsertCommands();
_pendingBulkInsertCommands.Clear();
}
base.AddCommand(modificationCommand);
}
}
@ -140,11 +148,11 @@ namespace EntityFrameworkCore.Jet.Update.Internal
IReadOnlyModificationCommand firstCommand,
IReadOnlyModificationCommand secondCommand)
=> firstCommand.TableName == secondCommand.TableName
&& firstCommand.Schema == secondCommand.Schema
&& firstCommand.ColumnModifications.Where(o => o.IsWrite).Select(o => o.ColumnName).SequenceEqual(
secondCommand.ColumnModifications.Where(o => o.IsWrite).Select(o => o.ColumnName))
&& firstCommand.ColumnModifications.Where(o => o.IsRead).Select(o => o.ColumnName).SequenceEqual(
secondCommand.ColumnModifications.Where(o => o.IsRead).Select(o => o.ColumnName));
&& firstCommand.Schema == secondCommand.Schema
&& firstCommand.ColumnModifications.Where(o => o.IsWrite).Select(o => o.ColumnName).SequenceEqual(
secondCommand.ColumnModifications.Where(o => o.IsWrite).Select(o => o.ColumnName))
&& firstCommand.ColumnModifications.Where(o => o.IsRead).Select(o => o.ColumnName).SequenceEqual(
secondCommand.ColumnModifications.Where(o => o.IsRead).Select(o => o.ColumnName));
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to

@ -5,6 +5,7 @@ using System.Globalization;
using System.Linq;
using System.Text;
using EntityFrameworkCore.Jet.Metadata;
using EntityFrameworkCore.Jet.Utilities;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
@ -34,6 +35,17 @@ namespace EntityFrameworkCore.Jet.Update.Internal
{
}
public override ResultSetMapping AppendInsertOperation(StringBuilder commandStringBuilder, IReadOnlyModificationCommand command,
int commandPosition, out bool requiresTransaction)
{
//No database columns need to be read back
if (command.ColumnModifications.All(o => !o.IsRead))
{
return AppendInsertReturningOperation(commandStringBuilder, command, commandPosition, out requiresTransaction);
}
return base.AppendInsertOperation(commandStringBuilder, command, commandPosition, out requiresTransaction);
}
public ResultSetMapping AppendBulkInsertOperation(StringBuilder commandStringBuilder, IReadOnlyList<IReadOnlyModificationCommand> modificationCommands, int commandPosition, out bool requiresTransaction)
{
var firstCommand = modificationCommands[0];

@ -95,7 +95,6 @@ WHERE @@ROWCOUNT = 1 AND `Id` = @@identity;
INSERT INTO `MeterReadingDetails` (`Id`, `CurrentRead`, `PreviousRead`)
VALUES (@p1, @p2, @p3);
SELECT @@ROWCOUNT;
""",
//
"""

@ -643,26 +643,24 @@ namespace EntityFrameworkCore.Jet.FunctionalTests
+ _eol
+ " `NotFigTime` datetime NOT NULL,"
+ _eol
+ " `ToEat` tinyint NOT NULL,"
+ " `ToEat` byte NOT NULL,"
+ _eol
+ " `OrNothing` float NOT NULL,"
+ " `OrNothing` double NOT NULL,"
+ _eol
+ " `Fuse` smallint NOT NULL,"
+ _eol
+ " `WayRound` bigint NOT NULL,"
+ " `WayRound` decimal(20,0) NOT NULL,"
+ _eol
+ " `On` real NOT NULL,"
+ " `On` single NOT NULL,"
+ _eol
+ " `AndChew` varbinary(max) NULL,"
+ " `AndChew` longbinary NULL,"
+ _eol
+ " `AndRow` rowversion NULL,"
+ " `AndRow` varbinary(8) NULL,"
+ _eol
+ " CONSTRAINT `PK_Blogs` PRIMARY KEY (`Key1`, `Key2`)"
+ _eol
+ ");"
+ _eol
+ "GO"
+ _eol
+ _eol
+ _eol,
script);

@ -312,7 +312,7 @@ CREATE INDEX `IX_Person_Name` ON `Person` (`Name`);
AssertSql(
@"ALTER TABLE `Person` ALTER COLUMN `Id` DROP DEFAULT;
ALTER TABLE `Person` ALTER COLUMN `Id` integer NOT NULL;
ALTER TABLE `Person` ALTER COLUMN `Id` decimal(20,0) NOT NULL;
");
}
@ -366,97 +366,97 @@ ALTER TABLE `Person` ALTER COLUMN `Id` integer NOT NULL;
");
}
// [ConditionalFact]
// public virtual void CreateDatabaseOperation_with_filename()
// {
// Generate(
// new JetCreateDatabaseOperation { Name = "Northwind", FileName = "Narf.mdf" });
//
// var expectedFile = Path.GetFullPath("Narf.mdf");
// var expectedLog = Path.GetFullPath("Narf_log.ldf");
//
// AssertSql(
// $@"CREATE DATABASE [Northwind]
// ON (NAME = 'Narf', FILENAME = '{expectedFile}')
// LOG ON (NAME = 'Narf_log', FILENAME = '{expectedLog}');
// GO
//
// IF SERVERPROPERTY('EngineEdition') <> 5
// BEGIN
// ALTER DATABASE [Northwind] SET READ_COMMITTED_SNAPSHOT ON;
// END;
// ");
// }
// [ConditionalFact]
// public virtual void CreateDatabaseOperation_with_filename_and_datadirectory()
// {
// var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
//
// Generate(
// new JetCreateDatabaseOperation { Name = "Northwind", FileName = "|DataDirectory|Narf.mdf" });
//
// var expectedFile = Path.Combine(baseDirectory, "Narf.mdf");
// var expectedLog = Path.Combine(baseDirectory, "Narf_log.ldf");
//
// AssertSql(
// $@"CREATE DATABASE [Northwind]
// ON (NAME = 'Narf', FILENAME = '{expectedFile}')
// LOG ON (NAME = 'Narf_log', FILENAME = '{expectedLog}');
// GO
//
// IF SERVERPROPERTY('EngineEdition') <> 5
// BEGIN
// ALTER DATABASE [Northwind] SET READ_COMMITTED_SNAPSHOT ON;
// END;
// ");
// }
// [ConditionalFact]
// public virtual void CreateDatabaseOperation_with_filename_and_custom_datadirectory()
// {
// var dataDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data");
//
// AppDomain.CurrentDomain.SetData("DataDirectory", dataDirectory);
//
// Generate(
// new JetCreateDatabaseOperation { Name = "Northwind", FileName = "|DataDirectory|Narf.mdf" });
//
// AppDomain.CurrentDomain.SetData("DataDirectory", null);
//
// var expectedFile = Path.Combine(dataDirectory, "Narf.mdf");
// var expectedLog = Path.Combine(dataDirectory, "Narf_log.ldf");
//
// AssertSql(
// $@"CREATE DATABASE [Northwind]
// ON (NAME = 'Narf', FILENAME = '{expectedFile}')
// LOG ON (NAME = 'Narf_log', FILENAME = '{expectedLog}');
// GO
//
// IF SERVERPROPERTY('EngineEdition') <> 5
// BEGIN
// ALTER DATABASE [Northwind] SET READ_COMMITTED_SNAPSHOT ON;
// END;
// ");
// }
// [ConditionalFact]
// public virtual void CreateDatabaseOperation_with_collation()
// {
// Generate(
// new JetCreateDatabaseOperation { Name = "Northwind", Collation = "German_PhoneBook_CI_AS" });
//
// AssertSql(
// @"CREATE DATABASE [Northwind]
// COLLATE German_PhoneBook_CI_AS;
// GO
//
// IF SERVERPROPERTY('EngineEdition') <> 5
// BEGIN
// ALTER DATABASE [Northwind] SET READ_COMMITTED_SNAPSHOT ON;
// END;
// ");
// }
// [ConditionalFact]
// public virtual void CreateDatabaseOperation_with_filename()
// {
// Generate(
// new JetCreateDatabaseOperation { Name = "Northwind", FileName = "Narf.mdf" });
//
// var expectedFile = Path.GetFullPath("Narf.mdf");
// var expectedLog = Path.GetFullPath("Narf_log.ldf");
//
// AssertSql(
// $@"CREATE DATABASE [Northwind]
// ON (NAME = 'Narf', FILENAME = '{expectedFile}')
// LOG ON (NAME = 'Narf_log', FILENAME = '{expectedLog}');
// GO
//
// IF SERVERPROPERTY('EngineEdition') <> 5
// BEGIN
// ALTER DATABASE [Northwind] SET READ_COMMITTED_SNAPSHOT ON;
// END;
// ");
// }
// [ConditionalFact]
// public virtual void CreateDatabaseOperation_with_filename_and_datadirectory()
// {
// var baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
//
// Generate(
// new JetCreateDatabaseOperation { Name = "Northwind", FileName = "|DataDirectory|Narf.mdf" });
//
// var expectedFile = Path.Combine(baseDirectory, "Narf.mdf");
// var expectedLog = Path.Combine(baseDirectory, "Narf_log.ldf");
//
// AssertSql(
// $@"CREATE DATABASE [Northwind]
// ON (NAME = 'Narf', FILENAME = '{expectedFile}')
// LOG ON (NAME = 'Narf_log', FILENAME = '{expectedLog}');
// GO
//
// IF SERVERPROPERTY('EngineEdition') <> 5
// BEGIN
// ALTER DATABASE [Northwind] SET READ_COMMITTED_SNAPSHOT ON;
// END;
// ");
// }
// [ConditionalFact]
// public virtual void CreateDatabaseOperation_with_filename_and_custom_datadirectory()
// {
// var dataDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Data");
//
// AppDomain.CurrentDomain.SetData("DataDirectory", dataDirectory);
//
// Generate(
// new JetCreateDatabaseOperation { Name = "Northwind", FileName = "|DataDirectory|Narf.mdf" });
//
// AppDomain.CurrentDomain.SetData("DataDirectory", null);
//
// var expectedFile = Path.Combine(dataDirectory, "Narf.mdf");
// var expectedLog = Path.Combine(dataDirectory, "Narf_log.ldf");
//
// AssertSql(
// $@"CREATE DATABASE [Northwind]
// ON (NAME = 'Narf', FILENAME = '{expectedFile}')
// LOG ON (NAME = 'Narf_log', FILENAME = '{expectedLog}');
// GO
//
// IF SERVERPROPERTY('EngineEdition') <> 5
// BEGIN
// ALTER DATABASE [Northwind] SET READ_COMMITTED_SNAPSHOT ON;
// END;
// ");
// }
// [ConditionalFact]
// public virtual void CreateDatabaseOperation_with_collation()
// {
// Generate(
// new JetCreateDatabaseOperation { Name = "Northwind", Collation = "German_PhoneBook_CI_AS" });
//
// AssertSql(
// @"CREATE DATABASE [Northwind]
// COLLATE German_PhoneBook_CI_AS;
// GO
//
// IF SERVERPROPERTY('EngineEdition') <> 5
// BEGIN
// ALTER DATABASE [Northwind] SET READ_COMMITTED_SNAPSHOT ON;
// END;
// ");
// }
[ConditionalFact]
public virtual void AlterDatabaseOperation_collation()
@ -694,8 +694,9 @@ VALUES ('John', 'Snow');
AssertSql(
@"INSERT INTO `People` (`First Name`)
VALUES ('John'),
('Daenerys');
VALUES ('John');
INSERT INTO `People` (`First Name`)
VALUES ('Daenerys');
");
}
@ -976,30 +977,18 @@ SELECT @@ROWCOUNT;
MigrationsSqlGenerationOptions.Idempotent);
AssertSql(
@"CREATE INDEX `IX_Table1_Column1` ON `Table1` (`Column1`) WHERE [Column1] IS NOT NULL;
@"CREATE INDEX `IX_Table1_Column1` ON `Table1` (`Column1`) WITH [Column1] IS NOT NULL;
");
}
[ConditionalFact]
public virtual void CreateIndex_generates_exec_when_legacy_filter_and_idempotent()
[ConditionalTheory(Skip = "No sequences")]
public override void Sequence_restart_operation(long? startsAt)
{
Generate(
modelBuilder =>
{
modelBuilder
.HasAnnotation(CoreAnnotationNames.ProductVersion, "1.1.0")
.Entity("Table1").Property<int?>("Column1");
},
migrationBuilder => migrationBuilder.CreateIndex(
name: "IX_Table1_Column1",
table: "Table1",
column: "Column1",
unique: true),
MigrationsSqlGenerationOptions.Idempotent);
base.Sequence_restart_operation(startsAt);
AssertSql(
@"CREATE UNIQUE INDEX `IX_Table1_Column1` ON `Table1` (`Column1`) WHERE `Column1` IS NOT NULL';
");
var expectedSql = startsAt.HasValue
? @$"ALTER SEQUENCE [dbo].[TestRestartSequenceOperation] RESTART WITH {startsAt};"
: @"ALTER SEQUENCE [dbo].[TestRestartSequenceOperation] RESTART;";
AssertSql(expectedSql);
}
[ConditionalFact]
@ -1021,7 +1010,7 @@ SELECT @@ROWCOUNT;
$@"ALTER TABLE `People` ADD `Birthday` datetime NOT NULL DEFAULT #2019-01-01#;
");
}
public JetMigrationsSqlGeneratorTest()
: base(
JetTestHelpers.Instance,

@ -159,7 +159,6 @@ WHERE ([c].[Capacity] IS NOT NULL) AND ([c].[FuelType] IS NOT NULL)
INSERT INTO `LicensedOperators` (`VehicleName`, `LicenseType`)
VALUES (@p0, @p1);
SELECT @@ROWCOUNT;
"""
,
"""

@ -132,11 +132,8 @@ OUTPUT INSERTED.[Id], INSERTED.[Computed], i._Position;
"""
INSERT INTO `Ducks` (`Id`, `Name`, `Quacks`, `ConcurrencyToken`)
VALUES (@p0, @p1, @p2, @p3);
SELECT @@ROWCOUNT;
INSERT INTO `Ducks` (`Id`, `Name`, `Quacks`, `ConcurrencyToken`)
VALUES (@p0, @p1, @p2, @p3);
SELECT @@ROWCOUNT;
""",
stringBuilder.ToString());
Assert.Equal(ResultSetMapping.NoResults, grouping);
@ -179,11 +176,8 @@ INNER JOIN @inserted0 i ON ([t].[Id] = [i].[Id]);
"""
INSERT INTO `Ducks`
DEFAULT VALUES;
SELECT @@ROWCOUNT;
INSERT INTO `Ducks`
DEFAULT VALUES;
SELECT @@ROWCOUNT;
""";
AssertBaseline(expectedText, stringBuilder.ToString());
Assert.Equal(ResultSetMapping.NoResults, grouping);

@ -27,13 +27,13 @@ namespace EntityFrameworkCore.Jet
});
});
});
var cookies = context.Set<Cookie>()
.ToList();
Assert.Single(cookies);
Assert.Equal(new DateTime(2021, 12, 31), cookies[0].BestServedBefore);
AssertSql(
$@"CREATE TABLE `Cookie` (
`CookieId` counter NOT NULL,
@ -44,7 +44,6 @@ namespace EntityFrameworkCore.Jet
INSERT INTO `Cookie` (`CookieId`, `Name`)
VALUES (1, 'Basic');
SELECT @@ROWCOUNT;
SELECT `c`.`CookieId`, `c`.`BestServedBefore`, `c`.`Name`
FROM `Cookie` AS `c`");
@ -60,7 +59,7 @@ FROM `Cookie` AS `c`");
{
entity.Property(e => e.CookieId)
.HasColumnType("counter");
entity.HasData(
new Cookie { CookieId = 1, Name = "Chocolate Chip" });
});
@ -69,11 +68,11 @@ FROM `Cookie` AS `c`");
{
entity.Property(e => e.BackeryId)
.HasColumnType("counter");
entity.HasData(
new Backery { BackeryId = 1, Name = "Bread & Cookies" });
});
builder.Entity<CookieBackery>(entity =>
{
entity.HasKey(e => new { e.CookieId, e.BackeryId });
@ -85,17 +84,17 @@ FROM `Cookie` AS `c`");
entity.HasOne(d => d.Backery)
.WithMany()
.HasForeignKey(d => d.BackeryId);
entity.HasData(
new CookieBackery { CookieId = 1, BackeryId = 1 });
});
});
var cookieBackeries = context.Set<CookieBackery>()
.Include(cb => cb.Cookie)
.Include(cb => cb.Backery)
.ToList();
Assert.Single(cookieBackeries);
Assert.Equal(1, cookieBackeries[0].Cookie.CookieId);
Assert.Equal(1, cookieBackeries[0].Backery.BackeryId);
@ -124,15 +123,12 @@ CREATE TABLE `CookieBackery` (
INSERT INTO `Backery` (`BackeryId`, `Name`)
VALUES (1, 'Bread & Cookies');
SELECT @@ROWCOUNT;
INSERT INTO `Cookie` (`CookieId`, `BestServedBefore`, `Name`)
VALUES (1, #1899-12-30#, 'Chocolate Chip');
SELECT @@ROWCOUNT;
INSERT INTO `CookieBackery` (`BackeryId`, `CookieId`)
VALUES (1, 1);
SELECT @@ROWCOUNT;
CREATE INDEX `IX_CookieBackery_BackeryId` ON `CookieBackery` (`BackeryId`);
@ -152,7 +148,7 @@ INNER JOIN `Backery` AS `b` ON `c`.`BackeryId` = `b`.`BackeryId`");
{
entity.Property(e => e.CookieId)
.HasColumnType("int");
entity.HasData(
new Cookie { CookieId = 1, Name = "Chocolate Chip" });
});
@ -161,11 +157,11 @@ INNER JOIN `Backery` AS `b` ON `c`.`BackeryId` = `b`.`BackeryId`");
{
entity.Property(e => e.BackeryId)
.HasColumnType("int");
entity.HasData(
new Backery { BackeryId = 1, Name = "Bread & Cookies" });
});
builder.Entity<CookieBackery>(entity =>
{
entity.HasKey(e => new { e.CookieId, e.BackeryId });
@ -177,17 +173,17 @@ INNER JOIN `Backery` AS `b` ON `c`.`BackeryId` = `b`.`BackeryId`");
entity.HasOne(d => d.Backery)
.WithMany()
.HasForeignKey(d => d.BackeryId);
entity.HasData(
new CookieBackery { CookieId = 1, BackeryId = 1 });
});
});
var cookieBackeries = context.Set<CookieBackery>()
.Include(cb => cb.Cookie)
.Include(cb => cb.Backery)
.ToList();
Assert.Single(cookieBackeries);
Assert.Equal(1, cookieBackeries[0].Cookie.CookieId);
Assert.Equal(1, cookieBackeries[0].Backery.BackeryId);
@ -216,15 +212,12 @@ CREATE TABLE `CookieBackery` (
INSERT INTO `Backery` (`BackeryId`, `Name`)
VALUES (1, 'Bread & Cookies');
SELECT @@ROWCOUNT;
INSERT INTO `Cookie` (`CookieId`, `BestServedBefore`, `Name`)
VALUES (1, #1899-12-30#, 'Chocolate Chip');
SELECT @@ROWCOUNT;
INSERT INTO `CookieBackery` (`BackeryId`, `CookieId`)
VALUES (1, 1);
SELECT @@ROWCOUNT;
CREATE INDEX `IX_CookieBackery_BackeryId` ON `CookieBackery` (`BackeryId`);
@ -244,7 +237,7 @@ INNER JOIN `Backery` AS `b` ON `c`.`BackeryId` = `b`.`BackeryId`");
{
entity.Property(e => e.CookieId)
.HasColumnType("int");
entity.HasData(
new Cookie { CookieId = 1, Name = "Chocolate Chip" });
});
@ -253,11 +246,11 @@ INNER JOIN `Backery` AS `b` ON `c`.`BackeryId` = `b`.`BackeryId`");
{
entity.Property(e => e.BackeryId)
.HasColumnType("int");
entity.HasData(
new Backery { BackeryId = 1, Name = "Bread & Cookies" });
});
builder.Entity<CookieBackery>(entity =>
{
entity.HasKey(e => new { e.CookieId, e.BackeryId });
@ -275,17 +268,17 @@ INNER JOIN `Backery` AS `b` ON `c`.`BackeryId` = `b`.`BackeryId`");
entity.HasOne(d => d.Backery)
.WithMany()
.HasForeignKey(d => d.BackeryId);
entity.HasData(
new CookieBackery { CookieId = 1, BackeryId = 1 });
});
});
var cookieBackeries = context.Set<CookieBackery>()
.Include(cb => cb.Cookie)
.Include(cb => cb.Backery)
.ToList();
Assert.Single(cookieBackeries);
Assert.Equal(1, cookieBackeries[0].Cookie.CookieId);
Assert.Equal(1, cookieBackeries[0].Backery.BackeryId);
@ -314,15 +307,12 @@ CREATE TABLE `CookieBackery` (
INSERT INTO `Backery` (`BackeryId`, `Name`)
VALUES (1, 'Bread & Cookies');
SELECT @@ROWCOUNT;
INSERT INTO `Cookie` (`CookieId`, `BestServedBefore`, `Name`)
VALUES (1, #1899-12-30#, 'Chocolate Chip');
SELECT @@ROWCOUNT;
INSERT INTO `CookieBackery` (`BackeryId`, `CookieId`)
VALUES (1, 1);
SELECT @@ROWCOUNT;
CREATE INDEX `IX_CookieBackery_BackeryId` ON `CookieBackery` (`BackeryId`);

Loading…
Cancel
Save