2017-05-10 47 views
0

我已經從我的客戶端獲得了一個有效內容,該對象的屬性是基元,而其他對象的屬性也是基元。EFCore更新沒有更新數據庫中的行

例如:

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); 

我做的.Select,因爲如果我不,那麼bar永遠不會被填充。

然後我更新什麼從客戶端出現的屬性:

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); 

但後來我得到一個錯誤The instance of entity type cannot be tracked because another instance of this type with the same key is already being tracked.

EDIT2:用簡單的_context.Update(request)更換所有的其他代碼工作中。我很好奇爲什麼其他方式不是。

+0

我也注意到這種行爲,從我收集它似乎是故意的。所有默認生成的代碼也都使用這種方式。既然你的問題已經闡明,也許你想添加你的EDIT2作爲答案? –

回答

2

聲明...

_context.MainObjs.Select(x => new MainObj { ... }) 

...不重視什麼背景。它只是創建一個新的對象,但EF不知道它。在EF6中,不允許在EF LINQ查詢中創建實體類型,這完全是爲了防止這種混淆。

因此,通過使用_context.MainObjs.Include(x =>x.bar),您確實附加了MainObj及其bar上下文,其更改將被跟蹤。

最後,聲明_context.Update(request)重視request上下文並將其標記爲Modified,包括它的外鍵,其bar財產。