我正在阅读有关使用Entity Framework 6
的缓存和性能的信息,并且在向数据库发出任何查询之前我有始终检查DbSet.Local
集合的这种意思,如果目的是查询是加载单个实体信息。所以这就是我提出的模式:
pubilc TAccount LoadByUsername<TAccount>(string username)
{
TAccount acc = null;
// Check cache.
acc = DbEntitySet.Local.FirstOrDefault(a => a.Username.Equals(username, StringComparison.CurrentCultureIgnoreCase));
if (acc == null) {
// Then try and load from db.
return await DbEntitySet.FirstOrDefaultAsync(u => u.Username.Equals(username)).WithCurrentCulture();
}
return acc;
}
考虑到避免db往返+数据库处理的好处,我认为检查Local的开销是可以忽略的。
话虽如此,我继续阅读Identity Framework源代码以检查它们是否做了类似的事情,我发现他们总是发出另一个查询,即使数据的可能性很高已经在记忆中,这意味着:
FindById(accId);
FindByUsername(username);
FindByUsername(username);
FindByUsername(username);
导致4次往返数据包,即使username
参数是FindById
加载的帐户的用户名。
这是我的问题:我在这里做点什么,或者这种模式是不安全的?我不确定我是否应该使用它,考虑到身份并没有使用类似的东西,而且作者显然比我有更多的知识。
DbSet.Local
这样安全吗?
- 更新
我刚发现一段代码破解了作为参数传递的LINQ查询,以检查它是否包含select by id,这样他们就可以在进入db之前检查实体的缓存(通过调用DbSet.Find
)。所以,我想我可以做些什么,只是无法理解为什么他们没有将这个想法扩展到诸如&#34; FindByEmail&#34;等方法。
答案 0 :(得分:0)
非常有趣的问题,我在这方面遇到了一些问题。
您发布的示例看起来很安全。您正在寻找具有已知键值的单个实体。不过,我认为你发现它在不同情况下并不安全。
例如,我已经继承了存储库首先使用本地(缓存)结果的一些代码,然后如果没有结果则返回向数据库发出查询:
public class Run extends Application {
@Override
public void start(final Stage primaryStage) {
Button button = new Button();
button.setText("Navigation");
button.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
Label secondLabel = new Label("Select from list");
StackPane secondaryLayout = new StackPane();
secondaryLayout.getChildren().add(secondLabel);
Scene secondScene = new Scene(secondaryLayout, 500, 400);
// New window (Stage)
Stage newWindow = new Stage();
newWindow.setTitle("Adding products");
newWindow.setScene(secondScene);
// Specifies the modality for new window.
newWindow.initModality(Modality.WINDOW_MODAL);
// Specifies the owner Window (parent) for new window
newWindow.initOwner(primaryStage);
// Set position of second window, related to primary window.
newWindow.setX(primaryStage.getX() + 200);
newWindow.setY(primaryStage.getY() + 100);
newWindow.show();
}
});
Button button2 = new Button();
button2.setText("X");
button2.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
Label secondLabel = new Label("Select from list");
StackPane secondaryLayout = new StackPane();
secondaryLayout.getChildren().add(secondLabel);
Scene secondScene = new Scene(secondaryLayout, 500, 400);
// New window (Stage)
Stage newWindow = new Stage();
newWindow.setTitle("Adding products");
newWindow.setScene(secondScene);
// Specifies the modality for new window.
newWindow.initModality(Modality.WINDOW_MODAL);
// Specifies the owner Window (parent) for new window
newWindow.initOwner(primaryStage);
// Set position of second window, related to primary window.
newWindow.setX(primaryStage.getX() + 200);
newWindow.setY(primaryStage.getY() + 100);
newWindow.show();
}
});
StackPane root = new StackPane();
root.getChildren().add(button);
root.getChildren().add(button2);
Scene scene = new Scene(root, 650, 450);
primaryStage.setTitle("Shopping Buddy");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
这在大多数情况下都很棒,但是在向LoadAll发出两个重叠结果请求时遇到了问题。例如加载带有图像1和2的图像列表,然后加载图像2和3中的图像列表。使用本地缓存完成两个查询,但第二个查询错误地仅包括图像2.图像3不在还有本地缓存。
我需要重新调整调用代码以将所有图像预加载到缓存中,或者我需要从任何返回列表的方法中删除本地缓存的结果。
当缓存的查询结果不够好并且发出非缓存查询时,我无法找到明显的方法。
MS发布了一篇文章,其中本地结果直接绑定到UI(https://msdn.microsoft.com/en-us/library/jj592872(v=vs.113).aspx)。这非常适合您希望能够进行更改并一次性提交所有内容的实例。不太确定它是否超越了这一点。