【发布时间】:2018-01-18 13:00:08
【问题描述】:
我遇到了一个奇怪的问题: 我有一个非常简单的 Login(string user, string pass) 用户登录方法,需要保存该用户的上次登录日期:
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 更新成功,其 Autogenerated 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,但 Entity Framework 知道如何处理它们没有问题,这是唯一的例外 - 这个 xUnit 测试。
问题很可能出在 dbContext.Entry(dbUser)... 行,因为当我将其注释掉时,测试正常通过。我什至认为那里不需要它,因为没有它,在常规调试中所有的更新都是一样的。 编辑:两者 - xUnit 测试和常规调试都使用相同的 ConnectionString。
什么可能导致这种奇怪的行为?我试图找到一些预运行配置,作为测试调试器和常规调试器访问此方法之间的一些差异,但找不到任何东西。
【问题讨论】:
-
您的 dbContext 从哪里获取连接字符串?确保它们指向同一个数据库?
-
是的,他们使用相同的连接字符串。我检查了那个。我更新了我的问题。感谢您指出。
-
由于您正在更新一个连接的实体,您不需要将整个对象标记为已修改。当您设置新字段值时,它会自动将特定字段标记为已修改。所以在这种情况下不需要 dbContext.Entry
-
如果您明确想将某个字段标记为已修改,请参阅stackoverflow.com/questions/3642371/…
标签: c# sql-server entity-framework sql-server-2016 xunit.net