如何添加条件以使用实体框架链接到实体来更新条目
本文关键字:实体 链接 框架 更新 何添加 添加 条件 | 更新日期: 2023-09-27 18:13:10
假设我有以下实体:
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以外的任何图书馆借阅一本书。
当您使用.Attach(book)
时,您实际上是在告诉EF:嘿,这些是数据库中现有记录的原始值。所以在你的例子中EF会认为现有的book.LibraryID
是1
。您可以利用这一事实,并通过配置LibraryID
属性来强制EF执行所需的检查,该属性将被数据注释用作乐观并发令牌:
public class Book
{
// ...
[ConcurrencyCheck]
public int LibraryID { get; set; }
}
或Fluent API:
modelBuilder.Entity<Book>()
.Property(e => e.LibraryID).IsConcurrencyToken();
现在,如果您打开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
。