我想找出在执行以下操作时使用这三种从数据库获取数据的方法的区别:
public T GetById(int id) {
using (var db = Database.Session) {
using (var t = db.BeginTransaction()) {
try {
return db.Get<T>(id);
}
catch (Exception) {
if (!t.WasCommitted) {
t.Rollback();
}
throw;
}
}
}
}
或
public T GetById(int id) {
using (var db = Database.Session) {
using (var t = db.BeginTransaction()) {
try {
return Query<T>().First(x=>x.Id == id);
//or something like
//return Query<T>().Where(x=>x.Id == id).FirstOrDefault();
//or
//return QueryOver<T>().Where(x=>x.Id == id).FirstOrDefault;
}
catch (Exception) {
if (!t.WasCommitted) {
t.Rollback();
}
throw;
}
}
}
}
甚至这样:
public T GetById(int id) {
using (var db = Database.Session) {
using (var t = db.BeginTransaction()) {
try {
return db.Load<T>(id);
}
catch (Exception) {
if (!t.WasCommitted) {
t.Rollback();
}
throw;
}
}
}
}
并向这个问题添加另一个问题,Query()
与 QueryOver()
有何不同?
我在 stackoverflow 中阅读了一些答案,但由于其中大部分是关于开始使用 Linq 和 NHibernate 3,我想知道今天的情况如何。
最佳答案
一般来说,我们有三种方法可以通过 ID 从数据库中获取实例。
1) 查询 - 这就是我们使用 QueryOver API( native NHibernate 语言)或查询(MS LINQ API 的实现)的地方。这些查询总是命中数据库(或缓存)并且可以加载完整的根对象,获取一些关系,或者只是投影(只有少数列/属性转换为一些 DTO)
2) 然后,我们有 Get<TEntity>()
,这是按 ID 获取项目的最常见方式。它总是命中数据库,因为它的契约(Contract)说(get):
Return the persistent instance of the given entity class with the given identifier, or null if there is no such persistent instance
因此,要确定对象是否存在,必须命中 DB。
3) 最后,还有第三个契约(Contract) - Load<TEntity>()
.它永远不会访问数据库来检查是否有这样的项目(具有提供的 ID):load() :
Return the persistent instance of the given entity class with the given identifier, assuming that the instance exists.
如果我们有一个引用 ID,并且我们知道它确实存在,我们应该使用 Load<TEntity>()
.
它将只是创建一个代理 - 使用提供的 ID 并且在该根/持有者实体的插入或更新期间,代理 ID 将用于创建正确的 SQL声明。
总结: Get()
和 Load()
为我们服务是有原因的。它们旨在支持不同的场景。
另见:
关于c# - NHibernate Query<T>、Get<T> 和 Load<T> 的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37178455/