C# 实体框架6使用另一条记录更新现有记录';s值

C# 实体框架6使用另一条记录更新现有记录';s值,c#,entity-framework,mvvm,C#,Entity Framework,Mvvm,我在我的应用程序中使用EF数据库第一个模型。这是WPF MVVM应用程序,所以我使用long living DbContext,它是在应用程序启动时创建的,在应用程序完成时释放 有两个表-客户端和设置设置以客户端id作为外键和设置id作为主键存储所有客户端设置。 在这个设置表中,我有一些settings\u id=1和client\u id=1的“默认”记录。我希望我的应用程序通过按下按钮恢复客户端的“默认”设置 在我的vewmodel中,我有一个类型为Client的ObservableColl

我在我的应用程序中使用EF数据库第一个模型。这是WPF MVVM应用程序,所以我使用long living DbContext,它是在应用程序启动时创建的,在应用程序完成时释放

有两个表-
客户端
设置
<代码>设置以
客户端id
作为外键和
设置id
作为主键存储所有客户端设置。 在这个
设置
表中,我有一些
settings\u id=1
client\u id=1
的“默认”记录。我希望我的应用程序通过按下按钮恢复客户端的“默认”设置

在我的vewmodel中,我有一个类型为
Client
ObservableCollection
,它是我的db实体模型类,还有一个类型为
Client
的属性
SelectedClient
,绑定到当前选定的客户端(在某些列表框中)。我还有实体类
设置
,它有一些字段表示设置表中的不同设置。我希望“默认”记录中的所有这些设置替换当前选定客户端的设置

那么我在做什么:

public void OnResetClientSettingsCommandExecute()
    {
        var defaultSettings = Global.DbContext.Settings.FirstOrDefault(c => c.client_id == 1);
        if (defaultSettings == null) return;

        var tmp = defaultSettings; 
        tmp.client_id = SelectedClient.client_id; // doing this to change the only field which needs to remain untouched            
        var selectedClientSettings = Global.DbContext.Settings.FirstOrDefault(c => c.client_id == SelectedClient.client_id);
        selectedClientSettings = tmp;

        Global.DbContext.SaveChanges();

    }
这个代码根本不起作用。我在这里得到的唯一一件事是将
settings
中我的'default'记录的
client\u id
更改为
SelectedClient
s client\u id。我不知道为什么会发生这种情况,我想如果我使用
tmp
就可以了,但不会。 我知道有一些使用
Attach()
方法或将实体的
状态更改为
Modified
的做法-我尝试了所有这些方法,但没有人为我工作,我想是因为我使用了长寿的DbContext方法

老实说,一般来说,我对更新应用程序中的记录感到非常困惑——我就是做不到,DbContext.SaveChanges()方法不会将更改保存到数据库,而是出于某种原因将它们回滚。所以我必须使用原始SQL查询,这有点像石器时代


请有人帮我找出我做错了什么。谢谢。

正确的方法。但这让人筋疲力尽

public void OnResetClientSettingsCommandExecute()
{
    var defaultSettings = Global.DbContext.Settings.FirstOrDefault(c => c.client_id == 1);
    if (defaultSettings == null) return;

    var selectedClientSettings = Global.DbContext.Settings.FirstOrDefault(c => c.client_id == SelectedClient.client_id);
    selectedClientSettings.serviceName = defaultSettings.serviceName;
    selectedClientSettings.write_delay = defaultSettings.write_delay;
    // etc...

    Global.DbContext.SaveChanges();
}

你应该考虑使用,它可以写得更容易。

你可以用这样的方法创建一个类

public static void CopyValues<T>(T source, T destination)
{
    var props = typeof(T).GetProperties();

    foreach(var prop in props)
    {
        var value = prop.GetValue(source);
        prop.SetValue(destination, value);
    }
}
publicstaticvoidcopyvalue(T源,T目标)
{
var props=typeof(T).GetProperties();
foreach(道具中的var道具)
{
var值=prop.GetValue(来源);
属性设置值(目的地、值);
}
}
然后将键指定给临时变量,复制其余属性并将键重新指定回其原始值

int id = selectedClientSettings.client_id;
ObjectCopier.CopyValues<Client>(defaultSettings, selectedClientSettings);
selectedClientSettings.client_id = id;
int id=selectedClientSettings.client\u id;
CopyValues(默认设置,selectedClientSettings);
selectedClientSettings.client\u id=id;

您想在数据库中创建另一行,使用默认设置值并链接到所选的客户端id,对吗?不,我已经有一行了,我想用默认字段替换它的所有字段,但客户端id字段除外。您应该注意到,您不能这样做<代码>var tmp=默认设置
不会创建新对象,它只会创建对现有对象的新引用。这就是为什么我问了一个问题-我意识到我的代码完全错误:)如果要更新selectedClientSettings,请逐个更新其值。或者你应该考虑使用AutoPAPER。这正是我一直在寻找的,但是现在它提出了一个ExtExopn,因为它试图复制主键。如何修改此选项以跳过将主键
设置\u id
从默认设置复制到选定的客户端设置?如果可以通过编程方式找到主键属性,可以在foreach循环中添加一些逻辑以跳过该属性。