Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 无法获取实体框架以生成DbUpdateConcurrencyException(数据库优先)_C#_Sql Server_Entity Framework_Entity Framework 6 - Fatal编程技术网

C# 无法获取实体框架以生成DbUpdateConcurrencyException(数据库优先)

C# 无法获取实体框架以生成DbUpdateConcurrencyException(数据库优先),c#,sql-server,entity-framework,entity-framework-6,C#,Sql Server,Entity Framework,Entity Framework 6,我正在尝试为EF实现乐观锁定模型。在我试图使用的表上有一个带有时间戳数据类型的列 我尝试通过修改T4脚本在成员上添加Timestamp属性。运行我的测试并发现它不起作用,然后我尝试以相同的方式(通过T4)在同一成员上添加ConcurrencyCheck属性。但是,在这两种情况下,生成的SQL实际上都没有在更新时使用该成员(如下所示)。我还在EDMX设计器中的属性上将并发模式设置为Fixed 在更新之后,我可以在单独的select中看到timestamp列,但在更新本身上看不到。我试着打开Save

我正在尝试为EF实现乐观锁定模型。在我试图使用的表上有一个带有时间戳数据类型的列

我尝试通过修改T4脚本在成员上添加
Timestamp
属性。运行我的测试并发现它不起作用,然后我尝试以相同的方式(通过T4)在同一成员上添加
ConcurrencyCheck
属性。但是,在这两种情况下,生成的SQL实际上都没有在更新时使用该成员(如下所示)。我还在EDMX设计器中的属性上将
并发模式
设置为
Fixed

在更新之后,我可以在单独的select中看到timestamp列,但在更新本身上看不到。我试着打开
SaveChanges()
,更改数据库记录,并在手动更新后看到时间戳值发生更改,执行
SaveChanges()
行,它执行得很好,没有引发异常。我是否缺少一些东西,我是否需要滚动自己的时间戳比较代码,或者我是否需要进入EF拦截器的世界来更改SQL输出?谢谢

生成的SQL:(通过
DbContext.Database.Log
记录)

T4生成后成员的最终版本:

[Timestamp]
[ConcurrencyCheck]
public byte[] fooversion { get; set; }
我想让EF做的是:

UPDATE [dbo].[Foo]
SET [FooTitle] = @0
WHERE ([FooId] = @1 AND [fooversion] = @2)

我决定使用自己的校验码。虽然它需要两次访问数据库,但它非常高效

我编写了一个接口,该接口连接到一系列已用于将内容连接到实体的分部类。它定义了一个查找选择器,我的实体基类服务可以使用它来获取特定版本。没有结果?返回消息。如果有结果,则实体将按预期更新

界面:

public interface IVersionableDbObject<TEntity>
    where TEntity : class, IValidatableObject
{
    byte[] Version { get; }
    Expression<Func<TEntity, bool>> LookupSelector { get; }
}
有趣的是,当更新实际发生时,EF仍然刷新行版本,而没有类似于我在OP中发布的SQL的
时间戳
并发检查
属性

public interface IVersionableDbObject<TEntity>
    where TEntity : class, IValidatableObject
{
    byte[] Version { get; }
    Expression<Func<TEntity, bool>> LookupSelector { get; }
}
public partial class Foo : IVersionableDbObject<Foo>
{
    public byte[] Version { get { return fooversion; } }

    public Expression<Func<Foo, bool>> LookupSelector
    {
        get { return foo => foo.FooId == FooId && foo.fooversion == Version; }
    }
}
IVersionableDbObject<TEntity> versionableSource = entity as IVersionableDbObject<TEntity>;
if (versionableSource != null)
{
    bool versionExists = innerContext.Set<TEntity>().Where(versionableSource.LookupSelector).Any();

    if (!versionExists)
        return new ValidationResult(string.Format(FooResources.EntityUpdateVersionConflictError,
                    BitConverter.ToInt32(versionableSource.Version, 0)));
}
SELECT 
CASE WHEN ( EXISTS (SELECT 
    1 AS [C1]
    FROM [dbo].[Foo] AS [Extent1]
    WHERE ([Extent1].[FooId] = @p__linq__0) AND ([Extent1].[fooversion] = @p__linq__1)
)) THEN cast(1 as bit) ELSE cast(0 as bit) END AS [C1]
FROM  ( SELECT 1 AS X ) AS [SingleRowTable1]