C# EFCore更新未更新数据库中的行

C# EFCore更新未更新数据库中的行,c#,entity-framework,entity-framework-core,C#,Entity Framework,Entity Framework Core,我的客户端提供了一个有效负载,它是一个属性为基本体的对象,以及其他属性也为基本体的对象 例如: public class MainObj { [Key] [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public int id {get;set;} public string foo {get;set;} public OtherObj bar {get;set;} } public class Oth

我的客户端提供了一个有效负载,它是一个属性为基本体的对象,以及其他属性也为基本体的对象

例如:

public class MainObj
{
   [Key]
   [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
   public int id {get;set;}
   public string foo {get;set;}
   public OtherObj bar {get;set;}
}

public class OtherObj
{
   [Key]
   [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
   public int id {get;set;}      
   public int test {get;set;}
}
验证请求后,我将获得用户尝试更新的对象:

var obj = _context.MainObjs.Select(x => new MainObj
{
     id = x.id,
     foo = x.foo,
     bar = x.bar
}).SingleOrDefaultAsync(x => x.id == request.id);
我正在做。选择,因为如果我不这样做,那么酒吧永远不会被填充

然后,我用客户端提供的内容更新属性:

obj.foo = request.foo;
obj.bar = request.bar;
然后我尝试保存更改:

_context.SaveChangesAsync();
但是,在执行此操作时,数据库中没有任何内容保持不变。我做错了什么?我过去只使用过EF6,所以我不知道EFCore在更新具有外键关系的对象时是否有什么奇怪的地方。很清楚,我的实际对象有比这更多的属性,但我不认为这是问题所在

编辑:我尝试使用.Include语法而不是.Select,如下所示:

var obj = _context.MainObjs.Include(x =>x.bar).SingleOrDefaultAsync(x => x.id == request.id);
但随后我得到一个错误,即无法跟踪实体类型的实例,因为已经在跟踪具有相同密钥的该类型的另一个实例

EDIT2:用简单的_context.Updaterequest替换所有其他代码正在工作。我很好奇为什么另一种方式不是

声明

_context.MainObjs.Select(x => new MainObj { ... })
。。。不会将任何内容附加到上下文。它只是创建了一个新的MainObj对象,但EF不知道。在EF6中,不允许在EF LINQ查询中创建实体类型,正是为了防止这种混淆

因此,通过使用_context.MainObjs.Includex=>x.bar,您可以将MainObj及其条附加到上下文中,并跟踪其更改

最后,语句_context.Updaterequest将请求附加到上下文并将其标记为已修改,包括其bar属性的外键。

语句

_context.MainObjs.Select(x => new MainObj { ... })
。。。不会将任何内容附加到上下文。它只是创建了一个新的MainObj对象,但EF不知道。在EF6中,不允许在EF LINQ查询中创建实体类型,正是为了防止这种混淆

因此,通过使用_context.MainObjs.Includex=>x.bar,您可以将MainObj及其条附加到上下文中,并跟踪其更改


最后,语句_context.Updaterequest将请求附加到上下文并将其标记为已修改,包括其bar属性的外键。

我也注意到了这种行为,从我收集的信息来看,这似乎是有意的。所有默认生成的代码也使用这种方式。既然你的问题陈述得很清楚,也许你想添加你的EDIT2作为答案?在你给定的代码中,你调用的是*异步方法,而不是在前面等待。这可能是个问题吗?我也注意到了这种行为,从我收集的信息来看,这似乎是故意的。所有默认生成的代码也使用这种方式。既然你的问题陈述得很清楚,也许你想添加你的EDIT2作为答案?在你给定的代码中,你调用的是*异步方法,而不是在前面等待。这可能是个问题吗?