我正在使用 Entity Framework 5 和 MySQL 数据库,只想更新 0 到 1 之间的行属性 "user_loginstatus"
。当我第一次通过客户端登录时,它更新得很好第一次尝试,再次尝试更新后,它毫无异常(exception)地没有执行任何操作。
我是这样登录的:
public async void LoginExecute()
{
// Checking Connection before etc...
if (await _dataService.IsLoginDataValidTask(UserObj.Username, md5))
{
Trace.WriteLine("LoginCommand Execute: Eingeloggt");
UserObj = await _dataService.GetUserDataTask(UserObj.Username);
await _dataService.SetUserStatusTask(UserObj.Id, 1);
await _dataService.WriteLog(UserObj.Id, "login", "Programm", GetLocalAdress());
Messenger.Default.Send(UserObj);
Messenger.Default.Send(new NotificationMessage("GoToMenuPage"));
}
else
{
// Error Stuff...
}
}
DataService类中的SetUserStatus方法
public Task SetUserStatusTask(int id, int status)
{
return Task.Factory.StartNew(() =>
{
try
{
var user = _entities.users.Find(id);
user.user_loginstatus = status;
_entities.SaveChanges();
}
catch (Exception ex)
{
Trace.WriteLine("DataService SetUserStatusTask: " + ex.Message);
}
});
}
DataService类中的GetUserData方法
public Task<User> GetUserDataTask(string username)
{
return Task.Factory.StartNew(() =>
{
try
{
var user = from us in _entities.users
where us.user_name.Equals(username)
select new User
{
Id = us.user_id,
Username = us.user_name,
FirstName = us.user_firstname,
LastName = us.user_lastname,
Gender = us.user_gender,
Email = us.user_mail,
Group = us.user_usergroup,
Avatar = us.user_avatar,
LoginStatus = 1
};
return user.FirstOrDefault();
}
catch (Exception ex)
{
Trace.WriteLine("DataService GetUserDataTask: " + ex);
return null;
}
});
}
所以“users”
是我的数据库表,“User”/“UserObj”
是我的自定义对象。
使用 Messenger
(来自 MVVM Light),我只需通过 MainViewModel 设置 View ,重置未使用的 ViewModel(ViewModel = new VieModel(...);
或 ViewModel = null;
)并传递当前/登录的用户对象。
使用相同的策略,我只是像这样注销
public ICommand LogoutCommand
{
get
{
return new RelayCommand(async () =>
{
await _dataService.SetUserStatusTask(CurrentUser.Id, 0);
if(CurrentUser.Id > 0 && IsLoggedIn)
await _dataService.WriteLog(CurrentUser.Id, "logout", "Programm", GetLocalAdress());
IsLoggedIn = false;
CurrentUser = new User();
Messenger.Default.Send(new NotificationMessage("GoToLoginPage"));
});
}
}
所以我可以经常使用正在运行的客户端登录,但是“user_loginStatus”
仅将第一次登录时间的更改设置为1然后返回0,但是当我注销时然后用同一用户重新登录,就不会再改变了。当我使用另一个用户登录(仍然是相同的正在运行的客户端)时,它第一次将“user_loginstatus”设置为 1,然后返回到 0,然后仅在我重新启动客户端时再次设置..
我可能做错了什么?
最佳答案
这基本上来 self 对原始问题的评论:
我多次遇到类似的问题。通常它是基于以下事实:您修改的实体无法正确验证,并且您的 dbContext 在没有适当异常的情况下失败,因为它仍然保留错误的实体。如果是这种情况,您可以通过使用作用域上下文并将数据访问操作嵌入到 using 语句中来规避此问题。
或者,您可以尝试明确告诉 EF 该实体已更改,例如:
_entities.Entry(user).State = EntityState.Modified;
关于您的其他问题:
理论上,您不必明确告诉 EF 实体的值已更改。更改跟踪应该自动执行此操作。我能想到的唯一异常(exception)是当您尝试修改明确不再跟踪的实体时。当您调用 _entities.Find(id) 时,它将在上下文中查找是否找到具有匹配主键值的对象并加载它。由于您之前已经修改过该对象,因此上下文将仅获取您已修改的旧对象来设置第一次登录状态。
这个“旧”对象可能不再被跟踪,您必须通过将其状态从附加更改为已修改来明确告诉 EF 它已更改。
关于c# - Entity Framework 5 更新对于每个对象/行仅有效一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35428296/