如何使用将动态填充的新字段进行迁移,例如通过将 EF 中的其他两个现有字段相乘

How can I make a migration with a new field that will be dynamically populated, for example by multiplying two other already existing fields in EF

我有实体 ProductItem 并且数据库已经通过使用此模板的迁移进行了更新:

public class ProductItem
    {
        public ProductItem()
        {
            Price = 0;
            Discount = 0;
        }
        public string Name { get; set; }

        public double Price { get; set; }

        public int Discount { get; set; }
    }

我的数据库中已经填充了一些实体。 我想再添加一个字段 TotalPrice:

public class ProductItem
    {
        public ProductItem()
        {
            Price = 0;
            Discount = 0;
            TotalPrice = 0;
        }
        public string Name { get; set; }

        public double Price { get; set; }

        public int Discount { get; set; }

        public double TotalPrice { get; set; }
    }

添加字段 TotalPrice 时,它将填充默认值,但我需要使用一个简单的公式 Price*(1 - Discount * 0.01) 来填充它每个字段。

这是我的新迁移代码,字段 TotalPrice:

    public partial class _addedTotalPrice : Migration
    {
        protected override void Up(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.AddColumn<double>(
                name: "TotalPrice",
                table: "ProductItems",
                type: "float",
                nullable: false,
                defaultValueSql: "ROUND(Price*(1 - Discount * 0.01),0)");

            migrationBuilder.UpdateData(
                table: "AspNetRoles",
                keyColumn: "Id",
                keyValue: "96ba8f64-053a-4574-a0bb-b73ecc88c761",
                column: "ConcurrencyStamp",
                value: "431db11e-8531-48bc-9483-5b13c0759d4e");

            migrationBuilder.UpdateData(
                table: "AspNetUsers",
                keyColumn: "Id",
                keyValue: "4c6e757b-ecb2-40a8-94fe-a2d3ecca28ca",
                columns: new[] { "ConcurrencyStamp", "PasswordHash" },
                values: new object[] { "390090d0-226e-43f6-af69-c3a139d602c0", "AQAAAAEAACcQAAAAEEcQUTyWcGF4TKR/qdtnDij7UjPt9NBtkwYw8WJX6CcVKnGBM8BuOj+YJVhYdgrA7A==" });
        }

        protected override void Down(MigrationBuilder migrationBuilder)
        {
            migrationBuilder.DropColumn(
                name: "TotalPrice",
                table: "ProductItems");

            migrationBuilder.UpdateData(
                table: "AspNetRoles",
                keyColumn: "Id",
                keyValue: "96ba8f64-053a-4574-a0bb-b73ecc88c761",
                column: "ConcurrencyStamp",
                value: "734fc36f-7481-4782-942f-61ec56112815");

            migrationBuilder.UpdateData(
                table: "AspNetUsers",
                keyColumn: "Id",
                keyValue: "4c6e757b-ecb2-40a8-94fe-a2d3ecca28ca",
                columns: new[] { "ConcurrencyStamp", "PasswordHash" },
                values: new object[] { "3209c2fd-5fc0-46a9-9689-b73b3b7617af", "AQAAAAEAACcQAAAAEMLDk9vuX+uj98bjcAPnzRvfHw37gfJttkgeQ+vkpXzoIbOdf0tyNcJ38/uzuNCyhA==" });
        }
    }
}

我试着用 defaultValueSql 来做,但它不起作用:

defaultValueSql: "ROUND(Price*(1 - Discount * 0.01),0)");

defaultValueSql: "SELECT ROUND(Price*(1 - Discount * 0.01),0) FROM dbo.ProductItems");

如何解决? 这是终端:

PM> dotnet ef database update 20210205151510__addedTotalPrice
Build started...
Build succeeded.
The Entity Framework tools version '5.0.1' is older than that of the runtime '5.0.2'. Update the tools for the latest features and bug fixes.
fail: Microsoft.EntityFrameworkCore.Database.Command[20102]
      Failed executing DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
      ALTER TABLE [ProductItems] ADD [TotalPrice] float NOT NULL DEFAULT (ROUND(Price*(1 - Discount * 0.01),0));
Failed executing DbCommand (2ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
ALTER TABLE [ProductItems] ADD [TotalPrice] float NOT NULL DEFAULT (ROUND(Price*(1 - Discount * 0.01),0));
Microsoft.Data.SqlClient.SqlException (0x80131904): РРјСЏ "Price" РЅРµ разрешено РІ данном контексте. Допустимыми выражениями являются константы, константные выражения Рё (РІ некоторых контекстах) переменные. Рмена столбцов РЅРµ разрешены.
   at Microsoft.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at Microsoft.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
   at Microsoft.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
   at Microsoft.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
   at Microsoft.Data.SqlClient.SqlCommand.RunExecuteNonQueryTds(String methodName, Boolean isAsync, Int32 timeout, Boolean asyncWrite)
   at Microsoft.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, Boolean sendToPipe, Int32 timeout, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry, String methodName)
   at Microsoft.Data.SqlClient.SqlCommand.ExecuteNonQuery()
   at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteNonQuery(RelationalCommandParameterObject parameterObject)
   at Microsoft.EntityFrameworkCore.Migrations.MigrationCommand.ExecuteNonQuery(IRelationalConnection connection, IReadOnlyDictionary`2 parameterValues)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.MigrationCommandExecutor.ExecuteNonQuery(IEnumerable`1 migrationCommands, IRelationalConnection connection)
   at Microsoft.EntityFrameworkCore.Migrations.Internal.Migrator.Migrate(String targetMigration)
   at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.UpdateDatabase(String targetMigration, String connectionString, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabaseImpl(String targetMigration, String connectionString, String contextType)
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.UpdateDatabase.<>c__DisplayClass0_0.<.ctor>b__0()
   at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
ClientConnectionId:9d817364-061a-4ade-b122-b50ca873140f
Error Number:128,State:1,Class:15
РРјСЏ "Price" РЅРµ разрешено РІ данном контексте. Допустимыми выражениями являются константы, константные выражения Рё (РІ некоторых контекстах) переменные. Рмена столбцов РЅРµ разрешены.
PM> 

您可以创建一个 SQL 脚本来更新数据库中所有现有条目的值。

例如假设您使用脚本 'UpdateTotalPrice.sql' 在迁移文件夹旁边创建了一个名为 'Sql' 的文件夹,您可以从迁移脚本

中执行它
SqlFile(@"Sql\UpdateTotalPrice.sql");

只需确保在 .sql 文件中将 'Copy to output directory' 设置为 true。

看起来 TotalPrice 列应该是计算列。 link 将指导您如何执行此操作:

此外,table 列不允许出现在 defaultValueSql 参数中