实体框架5更新仅对每个对象/行

时间:2016-02-16 09:15:51

标签: c# mysql wpf entity-framework mvvm

我正在将实体框架5与MySQL数据库一起使用,只是想在0和1之间更新行属性"user_loginstatus"。第一次通过客户端登录时,它会在第一次尝试后更新,试图再次更新它没有任何例外。

我这样登录:

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设置视图,重置未使用的ViewModels(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,然后仅在我重新启动客户端时再次设置..

我能做错什么?

2 个答案:

答案 0 :(得分:0)

在LoginExecute()中

你有UserObj,但在LogoutCommand()中你有CurrentUser。可以吗?

答案 1 :(得分:0)

这基本上来自我对原始问题的评论:

我有几次类似的问题。通常,它基于以下事实:您修改的实体无法正确验证,并且您的dbContext在没有正确异常的情况下失败,因为它仍然保留在false实体上。如果是这种情况,您可以通过使用作用域上下文并在using语句中嵌入数据访问操作来解决此问题。

或者你可以尝试明确告诉EF实体有变化,例如:

_entities.Entry(user).State = EntityState.Modified;

关于你的另一个问题:

理论上,您不应该明确告诉EF实体的价值已发生变化。更改跟踪应自动执行此操作。我能想到的唯一例外是,当您尝试修改明确不再被跟踪的实体时。当您调用_entities.Find(id)时,如果它找到具有匹配主键值的对象并加载它,它将在上下文中查找。由于您之前已经修改过此对象,因此上下文将只是获取您已修改的旧对象,以便第一次设置登录状态。

这个&#34; old&#34;对象可能不再被跟踪,你必须明确告诉EF它已经改变了,通过改变它的状态从附加到修改。