使用UDT主键插入记录时抛出OptimisticConcurrencyException

时间:2013-11-25 06:07:29

标签: .net sql sql-server entity-framework exception

我有一个如下所示的数据库表:

CREATE TABLE [dbo].[Configurations]
(
    [ConfigurationId] dbo.InternalRecordId NOT NULL PRIMARY KEY DEFAULT 1, 
    [EnableAuditLogging] BIT NOT NULL
)

请注意,主键的类型是用户定义的类型(UDT):

CREATE TYPE [dbo].[InternalRecordId]
    FROM int NOT NULL

此表中的记录映射到普通数据类型对象:

public class Configuration
{
    public int Id { get; set; }
    public bool EnableAuditLogging { get; set; }
}

我已将实体框架配置为将Id属性映射到ConfigurationId列作为非标识主键。我已经使用调试器来验证这个映射代码是否实际运行。

class ConfigurationMap : EntityTypeConfiguration<Entities.Configuration>
{
    public ConfigurationMap()
    {
        HasKey(t => t.Id);
        Property(t => t.Id)
            .HasColumnName("ConfigurationId")
            .HasDatabaseGeneratedOption(null);
    }
}

当我使用Entity Framework将记录插入表中时,如下所示:

var database = new LocalDbContext();
var configuration = new Configuration
{
    Id = 1,
};
database.Configurations.Add(configuration);
database.SaveChanges();

然后对SaveChanges的调用抛出一个OptimisticConcurrencyException,建议在插入后没有找到该记录。

我使用SQL Server Profiler来检查它在做什么:

INSERT [dbo].[Configurations]([EnableAuditLogging])
VALUES (@0)
SELECT [ConfigurationId]
FROM [dbo].[Configurations]
WHERE @@ROWCOUNT > 0 AND [ConfigurationId] = scope_identity()

我注意到它没有在ConfigurationId语句中指定INSERT的值,并且它也尝试从scope_identity获取值,即使它不是IDENTITY列。

当我将列的类型更改为int而不是UDT时,问题不再出现。

1 个答案:

答案 0 :(得分:0)

问题与这一行有关:

HasDatabaseGeneratedOption(null);

此方法的文档说明:

  

设置'null'将从属性中删除数据库生成的模式构面。设置'null'将导致与指定'None'相同的运行时行为。

尽管有第二句话,我还是尝试将其更改为:

HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

这解决了这个问题。因此,将其设置为null似乎执行与指定DatabaseGeneratedOption.None相同的操作。