gpt4 book ai didi

c# - 强制 EntityFramework 使用 OUTPUT 而不是 SCOPE_IDENTITY 来检索键值

转载 作者:太空狗 更新时间:2023-10-29 21:39:17 28 4
gpt4 key购买 nike

我首先使用实体​​框架代码访问一组表,这些表的键将由默认约束中基于 int 的 SEQUENCE 设置。 EF 似乎无法处理此问题,它坚持在插入后使用 SCOPE_IDENTITY 来填充整数键字段。

深入研究代码,它看起来有点硬编码:

http://entityframework.codeplex.com/SourceControl/latest#src/EntityFramework.SqlServer/SqlGen/DmlSqlGenerator.cs

在页面的中间位置查看 IsValidScopeIdentityColumnType 方法。如果此方法返回 true,则使用 SCOPE_IDENTITY() 检索插入的键值,否则生成 OUTPUT 子句。 (Guid/uniqueidentifier 是那里的典型用例)。

        // make sure it's a primitive type
if (typeUsage.EdmType.BuiltInTypeKind != BuiltInTypeKind.PrimitiveType)
{
return false;
}

// check if this is a supported primitive type (compare by name)
var typeName = typeUsage.EdmType.Name;

// integer types
if (typeName == "tinyint"
|| typeName == "smallint"
||
typeName == "int"
|| typeName == "bigint")
{
return true;
}

有什么方法可以让这个方法在整数字段上返回 false 吗?一旦我开始看到像“EDMType”这样的东西,我就超出了我对 EF 映射如何真正工作的真正理解。也许有某种方法可以使用用户定义的类型来欺骗它?但真正需要某种更新的是 .NET 端的配置。

另请参阅同一文件中的 UseGeneratedValuesVariable 方法以了解使用它的位置...

我不清楚为什么这里不全面使用 OUTPUT——也许是性能?

最佳答案

更新 - 数据库生成的 PK 仅支持身份

您可以创建一个标记为已计算的键列,它有一个 DataseGeneratedOption.Computed。 (参见 DataseGeneratedOption enum)。

为了表明这一点,您可以用 DatabaseGeneratedAttribute 修饰该列,或在 DbContext 的 OnModelCreating 方法中使用 Fluent API,如下所示:

        modelBuilder.Entity<EntityType>()
.Property(c => c.KeyColumn)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed)

此示例代码与 EF6.1 完美配合

public class MyDbContext : DbContext
{
public IDbSet<ComputedKey> ComputedKeys { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// Computed Key:
modelBuilder.Entity<ComputedKey>()
.HasKey(c => c.Id)
.Property(c => c.Id)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Computed);
}
}

public class ComputedKey
{
public int Id { get; set; }
}

当您运行应用程序时,表格会正确创建。

当您尝试将第一个实体添加到实体集合并保存更改时,就会出现问题。您得到: 不支持对主键列的属性“StoreGeneratedPattern”设置为“Computed”的表进行修改。请改用“身份”模式。关键列:'Id'。表:“CodeFirstDatabaseSchema.ComputedKey”

这是 EF(直到 6.1)的一个限制,它只允许将整数类型或 GUID 作为 DB 生成的 PK 值。

变通办法

首先:一种是使用在数据库上生成的列作为替代键。

从 EF 6.1 开始,您可以创建 AK,使用如下属性装饰 AK 列:

[Index("MyIndex", unique: true)]

第二:使用序列的原因是定义种子和增量。如果这是您需要的,您可以像这样修改身份:

DBCC CHECKIDENT ('SchemaName.TableName', RESEED, 10);

这意味着下一次生成的身份值将为11,增量为1。

如果您需要使用不同的增量,则需要删除并重新创建标识列,以指示种子和增量。但是要做到这一点,您还需要删除并创建关联的 foreingk 键,因此这太难实现了。

第三:你可以使用触发器。在触发器内,您可以使用 SET IDENTITY_INSERT tableName ON/OFF,但您可能会再次遇到问题,因为 @@identity 将不匹配。

注意:如果您需要运行自定义 SQL 命令来应用此自定义,则需要实现数据库初始化程序的 Seed 方法

结论

此方案仅部分受支持,因此您宁愿寻找替代解决方案,除非之前的解决方案之一适合您。

请求此功能

如果您对此功能感兴趣,请转到 Entity Framework 功能建议,并为此投票:Allow using SQL Server 2012 sequence for generating primary key

关于c# - 强制 EntityFramework 使用 OUTPUT 而不是 SCOPE_IDENTITY 来检索键值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23962690/

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