我遇到一个奇怪的问题: 我有一个非常简单的用户登录的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。
什么可能导致这种奇怪的行为?我试图找到一些预运行配置,在访问此方法作为测试调试器和常规调试器之间存在一些差异,但无法找到任何内容。
答案 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开始,一切都会正常插入和更新。