gpt4 book ai didi

oracle - Devart.Data.Oracle.EFCore - 如何使用序列来设置 PK 列值?

转载 作者:行者123 更新时间:2023-12-03 21:22:00 31 4
gpt4 key购买 nike

我将 Entity Framework Core 2.1.4 与 Oracle 11 数据库和 Devart.Data.Oracle.EFCore 提供程序一起使用。
数据库优先方法。

我想在插入时从 ID 列(主键)的序列值中获取,而无需每次都明确设置。
因此,基于与 SQL Server 的类似信息,我按以下方式进行了操作:

实体

public class Foo
{
public int Id { get; set; }
public double Value { get; set; }
}

映射(OnModelCreating 方法)
modelBuilder.HasSequence<int>("SEQ_FOOS", schema: "SCHEMA")
.StartsAt(1)
.IncrementsBy(1);

modelBuilder.Entity<Foo>(entity =>
{
entity.ForOracleToTable("FOOS");
entity.HasKey(e => e.Id);
entity.Property(e => e.Id).ForOracleHasColumnName("ID").IsRequired().ForOracleHasDefaultValueSql("SELECT SEQ_FOO.NEXTVAL FROM DUAL");
entity.Property(e => e.Value).HasColumnName("VALUE");
});

增值:
using (var dbContext = new FooDbContext())
{
var foo = new Foo()
{
Value = 5
};
dbContext.Foos.Add(foo);
dbContext.SaveChanges();
}

关于 SaveChanges:
OracleException: ORA-01400: cannot insert NULL into ("SCHEMA"."FOOS"."ID")

我还记录了 EF 查询。如您所见,插入中没有 ID 列:
INSERT INTO SCHEMA.FOOS (VALUE)
VALUES (:p0)

我试图简单地使用 SEQ_FOO.NEXTVAL 而不是全选或默认 EF 方法(如 HasDefaultValueSql),但没有任何效果。即使我输入:
ForOracleHasDefaultValueSql("asdasd");

这没有错误 - 只有与上面相同的异常(exception)。似乎 EF 从不调用该 SQL。

我错过了什么重要的东西吗?或者它可能是内部 Devart 问题?

最佳答案

好的,我有解决方案。看来我们需要使用ValueGenerator。我的实现如下。

映射

entity.Property(e => e.Id)
.ForOracleHasColumnName("ID")
.IsRequired()
.ValueGeneratedOnAdd()
.HasValueGenerator((_, __) => new SequenceValueGenerator(_defaultSchema, "SEQ_FOOS"));

SequenceValueGenerator(请注意,ValueGenerator 是 EF Core 类型)
internal class SequenceValueGenerator : ValueGenerator<int>
{
private string _schema;
private string _sequenceName;

public SequenceValueGenerator(string schema, string sequenceName)
{
_schema = schema;
_sequenceName = sequenceName;
}

public override bool GeneratesTemporaryValues => false;

public override int Next(EntityEntry entry)
{
using (var command = entry.Context.Database.GetDbConnection().CreateCommand())
{
command.CommandText = $"SELECT {_schema}.{_sequenceName}.NEXTVAL FROM DUAL";
entry.Context.Database.OpenConnection();
using (var reader = command.ExecuteReader())
{
reader.Read();
return reader.GetInt32(0);
}
}
}
}

它似乎按我的需要工作。

关于oracle - Devart.Data.Oracle.EFCore - 如何使用序列来设置 PK 列值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52853862/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com