2016-10-14 89 views
0

假設我有以下實體:如何添加條件,更新與實體框架LINQ到實體的條目

public class Library 
{ 
    public int ID { get; set; } 

    public ICollection<Book> Books { get; set; } 

    public Library() 
    { 
     Books = new HashSet<Book>(); 
    } 
} 
public class Book 
{ 
    public int ID { get; set; } 
    public int LibraryID { get; set; } 
    public string Title { get; set; } 
    public string Author { get; set; } 
    public DateTime PublicationDate { get; set; } 
    public bool CheckedOut { get; set; } 
} 

還有一堆庫,每個庫有一堆的書籍。 ID = 1的圖書館中的某人檢出ID = 42的圖書,因此我想將CheckedOut屬性更新爲true。假設無論出於什麼原因,我已經知道圖書館ID和書籍ID,但不知道其他信息。我可以不從數據庫中獲取的所有圖書數據很容易只更新CheckedOut屬性:

Book book=new Book(){ 
    ID=42, 
    LibraryID=1, 
    CheckedOut=true 
} 
context.Books.Attach(book); 
var entry=context.Entry(book); 
entry.Property(b=>b.CheckedOut).IsModified=true; 
context.SaveChanges(); 

這裏是我的問題。如果數據庫中的LibraryID不是1這本書,我該如何強制它失敗?在普通的SQL中,我可以編寫

UPDATE Books SET CheckedOut=1 WHERE ID=42 AND LibraryID=1 

我該如何對實體框架做同樣的事情?

一個很明顯的用例這裏是增加更多的安全性 - 例如,如果用戶沒有從其他任何庫比1

回答

2

當您使用.Attach(book),你檢查出一本書的權威性實際上告訴EF:嘿,這些是數據庫中現有記錄的原始值。所以在你的情況下,EF會認爲現有的book.LibraryID1。您可以利用這一事實,並迫使EF通過配置LibraryID財產用作Optimistic Concurrency Token通過兩種數據註釋來執行所需的檢查:

public class Book 
{ 
    // ... 
    [ConcurrencyCheck] 
    public int LibraryID { get; set; } 
} 

或流利的API:

​​

現在,如果你打開在EF記錄和執行你片斷,你會看到這樣的事情:

在14/10/2016 21時35分32秒+03

打開的連接:00

UPDATE [dbo].[Books] 
SET [CheckedOut] = @0 
WHERE (([ID] = @1) AND ([LibraryID] = @2)) 

-- @0: 'True' (Type = Boolean) 

-- @1: '42' (Type = Int32) 

-- @2: '1' (Type = Int32) 

這與您以後的相似。

此方法的唯一潛在問題是,當數據庫中的LibraryID不是1時,您將獲得DbUpdateConcurrencyException