简体   繁体   English

EF Core:添加带有十进制、非身份 PK 的记录

[英]EF Core: Add records with decimal, non-identity PK

I have an existing database with multiple tables with decimal ( numeric(14,0) ) PK columns.我有一个现有的数据库,其中包含多个带有十进制( numeric(14,0) )PK 列的表。 I'm experimenting with different ways to insert multiple records in one action.我正在尝试用不同的方法在一个动作中插入多条记录。

I'm not sure if I can introduce sequences, so I've been trying to use HasDefaultValueSql("MAX(CASE_ATTRIBUTE_ID) + 1") .我不确定是否可以引入序列,所以我一直在尝试使用HasDefaultValueSql("MAX(CASE_ATTRIBUTE_ID) + 1") In a general use case, you could have 1-n CaseAttributes added at a time, so I don't necessarily to use EF to query for the next ID first.在一般用例中,您可以一次添加 1-n 个 CaseAttributes,因此我不必先使用 EF 来查询下一个 ID。

I can probably add more detail, if necessary.如有必要,我可能会添加更多细节。 However, what would typically be the best way to insert 1-n records with EF Core without the presence of an auto-incrementing identity column?但是,在不存在自动递增标识列的情况下,使用 EF Core 插入 1-n 条记录的最佳方法通常是什么?

UDPATE: UDPATE:

Entity class except (I've tried both None and Computed ):实体类除外(我已经尝试了NoneComputed ):

[ExcludeFromCodeCoverage]
[Table("CASE_ATTRIBUTE_CONFIG", Schema = "dbo")]
public partial class CaseAttribute : ISoftDelete, IUpdateTracker
{
    [Key]
    [Column("CASE_ATTRIBUTE_ID", TypeName = "numeric(14, 0)"), DatabaseGenerated(DatabaseGeneratedOption.None)]
    public decimal CaseAttributeId { get; set; }
}

Context except:上下文除外:

modelBuilder.Entity<CaseAttribute>(entity =>
{
    entity.Property(e => e.CaseAttributeId).HasDefaultValueSql("MAX(CASE_ATTRIBUTE_ID) + 1").ValueGeneratedOnAdd();

    entity.HasQueryFilter(e => EF.Property<DateTime?>(e, "EffectiveEndDate") == null);
});

If I don't use ValueGeneratedOnAdd(), it just seems to insert '0'.如果我不使用 ValueGeneratedOnAdd(),它似乎只是插入了“0”。 Otherwise, I get the exception: Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> Microsoft.Data.SqlClient.SqlException (0x80131904): Cannot insert the value NULL into column 'CASE_ATTRIBUTE_ID', table 'RPE_V3_12_02_00.dbo.CASE_ATTRIBUTE_CONFIG'; column does not allow nulls. UPDATE fails.否则,我会收到异常: Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> Microsoft.Data.SqlClient.SqlException (0x80131904): Cannot insert the value NULL into column 'CASE_ATTRIBUTE_ID', table 'RPE_V3_12_02_00.dbo.CASE_ATTRIBUTE_CONFIG'; column does not allow nulls. UPDATE fails. Microsoft.EntityFrameworkCore.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> Microsoft.Data.SqlClient.SqlException (0x80131904): Cannot insert the value NULL into column 'CASE_ATTRIBUTE_ID', table 'RPE_V3_12_02_00.dbo.CASE_ATTRIBUTE_CONFIG'; column does not allow nulls. UPDATE fails.

Using profiler, you can see it also generates some really strange SQL:使用探查器,您可以看到它也生成了一些非常奇怪的 SQL:

exec sp_executesql N'SET NOCOUNT ON;
DECLARE @inserted0 TABLE ([CASE_ATTRIBUTE_ID] numeric(14, 0), [_Position] [int]);
MERGE [dbo].[CASE_ATTRIBUTE_CONFIG] USING (
VALUES (@p21, @p22, @p23, @p24, @p25, @p26, @p27, @p28, @p29, @p30, @p31, @p32, @p33, @p34, @p35, @p36, @p37, @p38, 0)) AS i ([CASE_ATTRIBUTE_NAME], [CASE_ATTRIBUTE_REGEX], [CASE_ATTRIBUTE_TYPE], [CASE_SUB_TYPE], [CASE_TYPE], [CODE], [CODE_TYPE], [CORE], [DISPLAY_GROUP_NAME], [DISPLAY_ORDER], [DISPLAY_TAB], [EFFECTIVE_BEGIN_DT], [EFFECTIVE_END_DT], [IS_REQUIRED], [MAXIMUM_LENGTH], [NODE_NAME], [UPDATED_BY], [UPDATED_DATE], _Position) ON 1=0
WHEN NOT MATCHED THEN
INSERT ([CASE_ATTRIBUTE_NAME], [CASE_ATTRIBUTE_REGEX], [CASE_ATTRIBUTE_TYPE], [CASE_SUB_TYPE], [CASE_TYPE], [CODE], [CODE_TYPE], [CORE], [DISPLAY_GROUP_NAME], [DISPLAY_ORDER], [DISPLAY_TAB], [EFFECTIVE_BEGIN_DT], [EFFECTIVE_END_DT], [IS_REQUIRED], [MAXIMUM_LENGTH], [NODE_NAME], [UPDATED_BY], [UPDATED_DATE])
VALUES (i.[CASE_ATTRIBUTE_NAME], i.[CASE_ATTRIBUTE_REGEX], i.[CASE_ATTRIBUTE_TYPE], i.[CASE_SUB_TYPE], i.[CASE_TYPE], i.[CODE], i.[CODE_TYPE], i.[CORE], i.[DISPLAY_GROUP_NAME], i.[DISPLAY_ORDER], i.[DISPLAY_TAB], i.[EFFECTIVE_BEGIN_DT], i.[EFFECTIVE_END_DT], i.[IS_REQUIRED], i.[MAXIMUM_LENGTH], i.[NODE_NAME], i.[UPDATED_BY], i.[UPDATED_DATE])
OUTPUT INSERTED.[CASE_ATTRIBUTE_ID], i._Position
INTO @inserted0;

SELECT [t].[CASE_ATTRIBUTE_ID] FROM [dbo].[CASE_ATTRIBUTE_CONFIG] t
INNER JOIN @inserted0 i ON ([t].[CASE_ATTRIBUTE_ID] = [i].[CASE_ATTRIBUTE_ID])
ORDER BY [i].[_Position];

',N'@p21 varchar(50),@p22 varchar(200),@p23 varchar(6),@p24 varchar(25),@p25 varchar(25),@p26 varchar(10),@p27 varchar(25),@p28 tinyint,@p29 varchar(100),@p30 decimal(1,0),@p31 varchar(25),@p32 datetime,@p33 datetime,@p34 bit,@p35 decimal(1,0),@p36 varchar(25),@p37 varchar(128),@p38 datetime',@p21='test-attribute',@p22=NULL,@p23='STR',@p24='ADMIN',@p25='MYTEST',@p26='MN',@p27='STATE_PROVINCE',@p28=4,@p29='display-group',@p30=1,@p31='',@p32='2020-10-01 00:00:00',@p33=NULL,@p34=0,@p35=4,@p36='node-name',@p37='admin@rsimail.com',@p38='2020-10-19 21:03:03.787'

I'm not sure if I can introduce sequences,我不确定我是否可以介绍序列,

Is there any technical reason not to use Sequences ?是否有任何技术原因不使用Sequences

You are configuring EF to generate the value on the server-side anyway.无论如何,您正在配置 EF 以在服务器端生成值。 A Sequence would be much more efficient in generating the values (and EF doesn't need to know how it's generated), and has the added benefit that manual inserts you do via SQL Management Studio will also leverage the sequence.序列在生成值时会更有效(并且 EF 不需要知道它是如何生成的),并且具有额外的好处,您通过 SQL Management Studio 执行的手动插入也将利用序列。

You can add an empty EF migration ( dotnet ef migrations add ... ) that creates the Sequence and updates the table to use the next value of the sequence as the default value for the primary key.您可以添加一个空的 EF 迁移 ( dotnet ef migrations add ... ),该dotnet ef migrations add ...创建序列并更新表以使用序列的下一个值作为主键的默认值。

Assuming the current MAX(CaseAttributeId) is 5000 :假设当前MAX(CaseAttributeId)5000

CREATE SEQUENCE [dbo].[CaseAttributeIdSequence] AS NUMERIC(14,0)
    START WITH 5001
    MINVALUE 5001
    INCREMENT BY 1
;

Update the table to use the next value of the sequence as the default value:更新表以使用序列的下一个值作为默认值:

ALTER TABLE [dbo].[CaseAttribute]
    ADD CONSTRAINT [DF_CaseAttribute_CaseAttributeId]
        DEFAULT NEXT VALUE FOR [dbo].[CaseAttributeIdSequence]
        FOR [CaseAttributeId]
;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM