实体框架(MSSQL 2016)+ xUnit测试 - 尝试更新“GENERATE ALWAYS”列SysStartTime

时间:2018-01-18 13:00:09

标签: c# sql-server entity-framework sql-server-2016 xunit.net

我遇到一个奇怪的问题: 我有一个非常简单的用户登录的Login(字符串用户,字符串传递)方法,需要保存该用户的上次登录日期:

using (MyDbContext dbContext = new MyDbContext())
{
    var dbUser = dbContext.IdentityUserLogins.SingleOrDefault(u => 
        u.LoginProvider == login && u.ProviderKey == password);
    if (dbUser != null)
    {
        dbUser.LastLoginDate = DateTime.Now;
        dbContext.Entry(dbUser).State = System.Data.Entity.EntityState.Modified;
        dbContext.SaveChanges();
        var id = Convert.ToInt32(dbUser.UserId);

        /*other stuff*/
    }
}

当我从常规调试运行时,一切正常。找到我输入的用户,他的LastLoginDate成功更新,其自动生成的SysStartTime在SaveChanges()

自动更新

但是当我从xUnit测试中运行此方法时,它表现得很奇怪。 测试很简单,如下:

[Fact]
[Trait("Category", "MyCategory")]
public void LoginTest()
{
    string user = /*user name*/
    string pass = /*get password hash*/
    UserModel user = handler.Login(user, pass);
    Assert.NotNull(user);
}

它只是调用该方法。

在SaveChanges()调用时出现问题,抛出异常:

Cannot update GENERATED ALWAYS columns in table 'AppIdentityUserLogin'

我们的表使用这些列,如SysStartTime,SysEndTime和RowVersion,但实体框架知道没有问题,如何处理它们,这是唯一的例外 - 这个xUnit测试。

问题最有可能发生在dbContext.Entry(dbUser)...行中,因为当我将其注释掉时,测试会正常通过。我甚至认为那里不需要它,因为没有它,一切都在常规调试中更新。 编辑:两个 - xUnit测试和常规调试使用相同的ConnectionString。

什么可能导致这种奇怪的行为?我试图找到一些预运行配置,在访问此方法作为测试调试器和常规调试器之间存在一些差异,但无法找到任何内容。

1 个答案:

答案 0 :(得分:0)

解决了它。 感谢Matt Ruwe和他对Temporal table problem的解决方案。

我只需告诉EF,不要试图覆盖Generated列。 在我的情况下,我必须将_namesToIgnore设置为" SysStartTime"和" SysEndTime"然后将此行放在我的BaseTest构造函数

System.Data.Entity.Infrastructure.Interception.DbInterception.Add(new EF.TemporalTableCommandTreeInterceptor());

现在,即使从xUnit test debug开始,一切都会正常插入和更新。